9#include <boost/test/unit_test.hpp>
18static
void microTask(
CScheduler& s, std::mutex& mutex,
int& counter,
int delta, std::chrono::system_clock::time_point rescheduleTime)
21 std::lock_guard<std::mutex> lock(mutex);
24 std::chrono::system_clock::time_point noTime = std::chrono::system_clock::time_point::min();
25 if (rescheduleTime != noTime) {
27 s.schedule(f, rescheduleTime);
45 std::mutex counterMutex[10];
46 int counter[10] = { 0 };
49 auto randomMsec = [](
FastRandomContext& rc) ->
int {
return -11 + (int)rc.randrange(1012); };
50 auto randomDelta = [](
FastRandomContext& rc) ->
int {
return -1000 + (int)rc.randrange(2001); };
52 std::chrono::system_clock::time_point start = std::chrono::system_clock::now();
53 std::chrono::system_clock::time_point now = start;
54 std::chrono::system_clock::time_point first, last;
58 for (
int i = 0; i < 100; ++i) {
59 std::chrono::system_clock::time_point t = now + std::chrono::microseconds(randomMsec(rng));
60 std::chrono::system_clock::time_point tReschedule = now + std::chrono::microseconds(500 + randomMsec(rng));
61 int whichCounter = zeroToNine(rng);
63 std::ref(counterMutex[whichCounter]), std::ref(counter[whichCounter]),
64 randomDelta(rng), tReschedule);
73 std::vector<std::thread> microThreads;
74 for (
int i = 0; i < 5; i++)
78 now = std::chrono::system_clock::now();
81 for (
int i = 0; i < 5; i++)
83 for (
int i = 0; i < 100; i++) {
84 std::chrono::system_clock::time_point t = now + std::chrono::microseconds(randomMsec(rng));
85 std::chrono::system_clock::time_point tReschedule = now + std::chrono::microseconds(500 + randomMsec(rng));
86 int whichCounter = zeroToNine(rng);
88 std::ref(counterMutex[whichCounter]), std::ref(counter[whichCounter]),
89 randomDelta(rng), tReschedule);
96 for (
auto& thread: microThreads) {
97 if (thread.joinable()) thread.join();
101 for (
int i = 0; i < 10; i++) {
103 counterSum += counter[i];
110 std::condition_variable condvar;
114 const auto no_wait= [&](
const std::chrono::seconds& d) {
115 return condvar.wait_until(lock, std::chrono::system_clock::now() - d);
118 BOOST_CHECK(std::cv_status::timeout == no_wait(std::chrono::seconds{1}));
119 BOOST_CHECK(std::cv_status::timeout == no_wait(std::chrono::minutes{1}));
120 BOOST_CHECK(std::cv_status::timeout == no_wait(std::chrono::hours{1}));
121 BOOST_CHECK(std::cv_status::timeout == no_wait(std::chrono::hours{10}));
122 BOOST_CHECK(std::cv_status::timeout == no_wait(std::chrono::hours{100}));
123 BOOST_CHECK(std::cv_status::timeout == no_wait(std::chrono::hours{1000}));
138 std::vector<std::thread> threads;
139 for (
int i = 0; i < 5; ++i) {
150 for (
int i = 0; i < 100; ++i) {
152 bool expectation = i == counter1++;
157 bool expectation = i == counter2++;
164 for (
auto& thread: threads) {
165 if (thread.joinable()) thread.join();
186 std::chrono::system_clock::time_point first, last;
190 std::thread scheduler_thread([&]() { scheduler.
serviceQueue(); });
196 scheduler.
scheduleFromNow([&scheduler] { scheduler.
stop(); }, std::chrono::milliseconds{1});
197 scheduler_thread.join();
207 std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
208 int delta = std::chrono::duration_cast<std::chrono::seconds>(first - now).count();
Simple class for background tasks that should be run periodically or once "after a while".
void serviceQueue()
Services the queue 'forever'.
void scheduleFromNow(Function f, std::chrono::milliseconds delta)
Call f once after the delta has passed.
void schedule(Function f, std::chrono::system_clock::time_point t)
Call func at/after time t.
void StopWhenDrained()
Tell any threads running serviceQueue to stop when there is no work left to be done.
std::function< void()> Function
void MockForward(std::chrono::seconds delta_seconds)
Mock the scheduler to fast forward in time.
size_t getQueueInfo(std::chrono::system_clock::time_point &first, std::chrono::system_clock::time_point &last) const
Returns number of tasks waiting to be serviced, and first and last task times.
void stop()
Tell any threads running serviceQueue to stop as soon as the current task is done.
uint64_t randrange(uint64_t range) noexcept
Generate a random integer in the range [0..range).
Class used by CScheduler clients which may schedule multiple jobs which are required to be run serial...
void AddToProcessQueue(std::function< void()> func)
Add a callback to be executed.
BOOST_AUTO_TEST_SUITE(cuckoocache_tests)
Test Suite for CuckooCache.
BOOST_AUTO_TEST_SUITE_END()
#define BOOST_CHECK_EQUAL(v1, v2)
#define BOOST_CHECK(expr)
static void microTask(CScheduler &s, std::mutex &mutex, int &counter, int delta, std::chrono::system_clock::time_point rescheduleTime)
BOOST_AUTO_TEST_CASE(manythreads)
#define WAIT_LOCK(cs, name)
void UninterruptibleSleep(const std::chrono::microseconds &n)