mirror of
https://github.com/XRPLF/clio.git
synced 2025-11-04 11:55:51 +00:00
@@ -41,10 +41,16 @@ CoroutineGroup::~CoroutineGroup()
|
||||
ASSERT(childrenCounter_ == 0, "CoroutineGroup is destroyed without waiting for child coroutines to finish");
|
||||
}
|
||||
|
||||
bool
|
||||
CoroutineGroup::canSpawn() const
|
||||
{
|
||||
return not maxChildren_.has_value() or childrenCounter_ < *maxChildren_;
|
||||
}
|
||||
|
||||
bool
|
||||
CoroutineGroup::spawn(boost::asio::yield_context yield, std::function<void(boost::asio::yield_context)> fn)
|
||||
{
|
||||
if (maxChildren_.has_value() && childrenCounter_ >= *maxChildren_)
|
||||
if (not canSpawn())
|
||||
return false;
|
||||
|
||||
++childrenCounter_;
|
||||
|
||||
@@ -54,6 +54,14 @@ public:
|
||||
*/
|
||||
~CoroutineGroup();
|
||||
|
||||
/**
|
||||
* @brief Check if a new coroutine can be spawned (i.e. there is space for a new coroutine in the group)
|
||||
*
|
||||
* @return true If a new coroutine can be spawned. false if the maximum number of coroutines has been reached
|
||||
*/
|
||||
bool
|
||||
canSpawn() const;
|
||||
|
||||
/**
|
||||
* @brief Spawn a new coroutine in the group
|
||||
*
|
||||
|
||||
@@ -218,21 +218,21 @@ ConnectionHandler::parallelRequestResponseLoop(Connection& connection, boost::as
|
||||
closeConnectionGracefully &= closeGracefully;
|
||||
break;
|
||||
}
|
||||
|
||||
bool const spawnSuccess = tasksGroup.spawn(
|
||||
yield, // spawn on the same strand
|
||||
[this, &stop, &closeConnectionGracefully, &connection, request = std::move(expectedRequest).value()](
|
||||
boost::asio::yield_context innerYield
|
||||
) mutable {
|
||||
auto maybeCloseConnectionGracefully = processRequest(connection, request, innerYield);
|
||||
if (maybeCloseConnectionGracefully.has_value()) {
|
||||
stop = true;
|
||||
closeConnectionGracefully &= maybeCloseConnectionGracefully.value();
|
||||
if (tasksGroup.canSpawn()) {
|
||||
bool const spawnSuccess = tasksGroup.spawn(
|
||||
yield, // spawn on the same strand
|
||||
[this, &stop, &closeConnectionGracefully, &connection, request = std::move(expectedRequest).value()](
|
||||
boost::asio::yield_context innerYield
|
||||
) mutable {
|
||||
auto maybeCloseConnectionGracefully = processRequest(connection, request, innerYield);
|
||||
if (maybeCloseConnectionGracefully.has_value()) {
|
||||
stop = true;
|
||||
closeConnectionGracefully &= maybeCloseConnectionGracefully.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (not spawnSuccess) {
|
||||
);
|
||||
ASSERT(spawnSuccess, "The coroutine was expected to be spawned");
|
||||
} else {
|
||||
connection.send(
|
||||
Response{
|
||||
boost::beast::http::status::too_many_requests,
|
||||
|
||||
@@ -33,10 +33,12 @@
|
||||
#include <boost/beast/core/flat_buffer.hpp>
|
||||
#include <boost/beast/core/stream_traits.hpp>
|
||||
#include <boost/beast/core/tcp_stream.hpp>
|
||||
#include <boost/beast/http.hpp>
|
||||
#include <boost/beast/http/field.hpp>
|
||||
#include <boost/beast/http/message.hpp>
|
||||
#include <boost/beast/http/string_body.hpp>
|
||||
#include <boost/beast/http/verb.hpp>
|
||||
#include <boost/beast/http/write.hpp>
|
||||
#include <boost/beast/ssl/ssl_stream.hpp>
|
||||
#include <boost/beast/version.hpp>
|
||||
#include <openssl/err.h>
|
||||
|
||||
@@ -165,3 +165,17 @@ TEST_F(CoroutineGroupTests, TooManyCoroutines)
|
||||
callback3_.Call();
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(CoroutineGroupTests, CanSpawn)
|
||||
{
|
||||
EXPECT_CALL(callback1_, Call);
|
||||
|
||||
runSpawn([this](boost::asio::yield_context yield) {
|
||||
CoroutineGroup group{yield, 1};
|
||||
EXPECT_TRUE(group.canSpawn());
|
||||
group.spawn(yield, [&group, this](boost::asio::yield_context) {
|
||||
callback1_.Call();
|
||||
EXPECT_FALSE(group.canSpawn());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user