11# include <gtest/gtest.h>
18# include <condition_variable>
88 return chrono::duration_cast<chrono::milliseconds>(
133 this_thread::sleep_for(chrono::milliseconds(100));
148 bool executed =
false;
163 ASSERT_TRUE(cv.wait_for(lock, chrono::milliseconds(500),
164 [&]{ return callback_done; }));
180 this_thread::sleep_for(chrono::milliseconds(200));
193 this_thread::sleep_for(chrono::milliseconds(200));
226 this_thread::sleep_for(chrono::milliseconds(100));
268 this_thread::sleep_for(chrono::milliseconds(50));
272 this_thread::sleep_for(chrono::milliseconds(200));
295 this_thread::sleep_for(chrono::milliseconds(400));
325 this_thread::sleep_for(chrono::milliseconds(400));
355 this_thread::sleep_for(chrono::milliseconds(600));
374 this_thread::sleep_for(chrono::milliseconds(100));
383 throw runtime_error(
"Test exception");
391 this_thread::sleep_for(chrono::milliseconds(300));
404 event->set_for_deletion();
423 this_thread::sleep_for(chrono::milliseconds(
expected_delay + 100));
439 atomic<int> executed_count{0};
440 const int num_threads = 4;
446 for (
int t = 0; t < num_threads; ++t)
448 threads.emplace_back([&, t]() {
463 for (
auto& t : threads)
466 this_thread::sleep_for(chrono::milliseconds(400));
478 atomic<int> canceled_count{0};
488 for (
int t = 0; t < 2; ++t)
490 threads.emplace_back([&, t]() {
496 }
catch (
const std::invalid_argument&) {
503 for (
auto& t : threads)
552 this_thread::sleep_for(chrono::milliseconds(250));
588 this_thread::sleep_for(chrono::milliseconds(200));
599 for (
int i = 0; i < 5; ++i)
634 this_thread::sleep_for(chrono::milliseconds(250));
660 this_thread::sleep_for(chrono::milliseconds(150));
687 this_thread::sleep_for(chrono::milliseconds(200));
694 this_thread::sleep_for(chrono::milliseconds(150));
772 EXPECT_EQ(e->get_name(),
"TestEventName");
774 e->set_name(
"NewName");
793 this_thread::sleep_for(chrono::milliseconds(200));
815 this_thread::sleep_for(chrono::milliseconds(50));
842 auto id1 =
e1->get_id();
843 auto id2 =
e2->get_id();
871 auto id1 =
e1->get_id();
872 auto id2 =
e2->get_id();
903 auto id = e->get_id();
927 testing::internal::CaptureStderr();
936 string output = testing::internal::GetCapturedStderr();
952 testing::internal::CaptureStderr();
965 string output = testing::internal::GetCapturedStderr();
973#if defined(__SANITIZE_THREAD__)
975# define TSAN_ENABLED 1
980# if __has_feature(thread_sanitizer)
981# define TSAN_ENABLED 1
1000 },
"In_Queue.*use-after-free");
1016 this_thread::sleep_for(chrono::milliseconds(90));
1021 this_thread::sleep_for(chrono::milliseconds(200));
1042 this_thread::sleep_for(chrono::milliseconds(50));
1046 this_thread::sleep_for(chrono::milliseconds(350));
1051 this_thread::sleep_for(chrono::milliseconds(300));
1080 bad.tv_nsec = 2000000000;
1088 bad.tv_nsec = 2000000000;
1109 std::condition_variable cv;
1114 std::lock_guard<std::mutex>
lk(m);
1124 std::unique_lock<std::mutex>
lk(m);
1125 ASSERT_TRUE(cv.wait_for(
lk, std::chrono::milliseconds(500), [&]{ return callbacks == 1; }));
1176 this_thread::sleep_for(chrono::milliseconds(10));
1196 this_thread::sleep_for(chrono::milliseconds(10));
1205 this_thread::sleep_for(chrono::milliseconds(100));
1228 this_thread::sleep_for(chrono::milliseconds(200));
1279 this_thread::sleep_for(chrono::milliseconds(10));
1298 this_thread::sleep_for(chrono::milliseconds(400));
1314 atomic<int> executed_count{0};
1325 this_thread::sleep_for(chrono::milliseconds(300));
1342 ::testing::InitGoogleTest(&
argc,
argv);
Time time_plus_msec(const Time ¤t_time, const int &msec)
size_t size() const noexcept
Count the number of elements of the list.
atomic< int > execution_count
void EventFct() override
Event handler function to be overridden.
ReschedulingEvent(const Time &t, TimeoutQueue *q, int max_resc)
void EventFct() override
Event handler function to be overridden.
SignalingEvent(const Time &t, mutex &m, condition_variable &c, bool &f)
function< void()> callback
void EventFct() override
Event handler function to be overridden.
TestEvent(const Time &t, function< void()> cb)
atomic< int > execution_count
Base class for scheduled events.
Event(const Time &t, std::string name="")
Execution_Status
Possible states of an event in its lifecycle.
@ Out_Queue
Not currently in any queue.
@ Canceled
Removed from queue before execution.
@ Executed
Completed execution.
@ In_Queue
Scheduled and waiting for trigger time.
@ To_Delete
Marked for cleanup.
void set_completion_callback(CompletionCallback cb)
Set the completion callback (called after EventFct completes or the event is canceled)
virtual void EventFct()=0
Event handler function to be overridden.
static constexpr EventId InvalidId
Invalid/null event ID.
Thread-safe priority queue for scheduling timed events.
size_t executed_count() const
Get count of events that have been executed.
void reschedule_event(const Time &trigger_time, Event *event)
Reschedule an event to a new time.
void reset_stats()
Reset statistics counters to zero.
size_t size() const
Get the number of pending events in the queue.
void schedule_event(const Time &trigger_time, Event *)
Schedule an event at a specific time.
bool is_running() const
Check if the queue is running (not shut down)
Time next_event_time() const
Get the trigger time of the next (soonest) event.
bool cancel_by_id(Event::EventId id)
Cancel a scheduled event by its ID.
void resume()
Resume event execution after pause.
size_t canceled_count() const
Get count of events that have been canceled.
void pause()
Pause event execution (events remain scheduled but won't execute)
void cancel_delete_event(Event *&event)
Cancel and delete an event.
void shutdown()
Shut down the queue and stop the background thread.
bool wait_until_empty(int timeout_ms=0)
Block until all pending events have been executed or canceled.
void schedule_after_ms(int ms_from_now, Event *event)
Schedule an event relative to the current time.
bool is_paused() const
Check if the queue is paused.
Event * find_by_id(const Event::EventId id) const
Find a scheduled event by its ID.
bool cancel_event(Event *event)
Cancel a scheduled event.
size_t clear_all()
Cancel all pending events in the queue.
bool is_empty() const
Check if the queue has no pending events.
chrono::steady_clock::time_point scheduled_at
chrono::steady_clock::time_point executed_at
TimingEvent(const Time &t)
void EventFct() override
Event handler function to be overridden.
bool completed() const noexcept
Return true if all underlying iterators are finished.
DynList< T > maps(const C &c, Op op)
Classic map operation.
Priority queue for scheduling timed events.
static TimeoutQueue * g_queue
static Time time_from_now_ms(int ms)