mirror of
https://github.com/XRPLF/clio.git
synced 2025-12-03 18:15:51 +00:00
feat: Repeating operations for util::async (#1776)
Async framework needed a way to do repeating operations (think simplest cases like AmendmentBlockHandler). This PR implements the **absolute minimum**, barebones repeating operations that - Can't return any values (void) - Do not take any arguments in the user-provided function - Can't be scheduled (i.e. a delay before starting repeating) - Can't be stopped from inside the user block of code (i.e. does not have stop token or anything like that) - Can be stopped through the RepeatedOperation's `abort()` function (but not from the user-provided repeating function)
This commit is contained in:
@@ -17,15 +17,20 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "util/Profiler.hpp"
|
||||
#include "util/async/Operation.hpp"
|
||||
#include "util/async/context/BasicExecutionContext.hpp"
|
||||
#include "util/async/context/SyncExecutionContext.hpp"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <semaphore>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
using namespace util::async;
|
||||
using ::testing::Types;
|
||||
@@ -36,6 +41,12 @@ template <typename T>
|
||||
struct ExecutionContextTests : public ::testing::Test {
|
||||
using ExecutionContextType = T;
|
||||
ExecutionContextType ctx{2};
|
||||
|
||||
~ExecutionContextTests() override
|
||||
{
|
||||
ctx.stop();
|
||||
ctx.join();
|
||||
}
|
||||
};
|
||||
|
||||
TYPED_TEST_CASE(ExecutionContextTests, ExecutionContextTypes);
|
||||
@@ -167,6 +178,23 @@ TYPED_TEST(ExecutionContextTests, timerUnknownException)
|
||||
EXPECT_TRUE(std::string{err}.ends_with("unknown"));
|
||||
}
|
||||
|
||||
TYPED_TEST(ExecutionContextTests, repeatingOperation)
|
||||
{
|
||||
auto const repeatDelay = std::chrono::milliseconds{1};
|
||||
auto const timeout = std::chrono::milliseconds{15};
|
||||
auto callCount = 0uz;
|
||||
|
||||
auto res = this->ctx.executeRepeatedly(repeatDelay, [&] { ++callCount; });
|
||||
auto timeSpent = util::timed([timeout] { std::this_thread::sleep_for(timeout); }); // calculate actual time spent
|
||||
|
||||
res.abort(); // outside of the above stopwatch because it blocks and can take arbitrary time
|
||||
auto const expectedPureCalls = timeout.count() / repeatDelay.count();
|
||||
auto const expectedActualCount = timeSpent / repeatDelay.count();
|
||||
|
||||
EXPECT_GE(callCount, expectedPureCalls / 2u); // expect at least half of the scheduled calls
|
||||
EXPECT_LE(callCount, expectedActualCount); // never should be called more times than possible before timeout
|
||||
}
|
||||
|
||||
TYPED_TEST(ExecutionContextTests, strandMove)
|
||||
{
|
||||
auto strand = this->ctx.makeStrand();
|
||||
|
||||
Reference in New Issue
Block a user