ATLAS Offline Software
Loading...
Searching...
No Matches
EventLoopUtils.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4#ifndef TRIGSERVICES_EVENTLOOPUTILS_H
5#define TRIGSERVICES_EVENTLOOPUTILS_H
6#include <atomic>
7#include <chrono>
8#include <condition_variable>
9#include <functional>
10#include <memory>
11#include <mutex>
12#include <thread>
13
14namespace HLT {
16 class LoopThread {
17 private:
19 std::condition_variable m_cond;
21 std::mutex m_mutex;
23 std::atomic<bool> m_keepRunning{true};
25 std::atomic<bool> m_started{false};
27 std::atomic<bool> m_finished{false};
29 std::function<void()> m_callback;
33 std::unique_ptr<std::thread> m_thread;
34
36 inline void waitForCond(std::unique_lock<std::mutex>& lock) {
38 m_cond.wait(lock);
39 } else {
40 m_cond.wait_for(lock, std::chrono::milliseconds(m_callbackIntervalMilliseconds));
41 }
42 }
43
45 void run() {
46 if (!m_keepRunning) {return;}
47 std::unique_lock<std::mutex> lock{m_mutex};
48
49 // first call outside the loop to set the m_started flag
50 waitForCond(lock);
51 m_started = true;
52 m_callback();
53
54 // subsequent calls in a loop
55 while(m_keepRunning) {
56 waitForCond(lock);
57 m_callback();
58 }
59 m_finished = true;
60 }
61
62 public:
63 explicit LoopThread(std::function<void()>&& callback, int callbackInterval=-1)
64 : m_callback(std::move(callback)),
65 m_callbackIntervalMilliseconds(callbackInterval),
66 m_thread(std::make_unique<std::thread>([this]{run();})) {}
67
69 wait();
70 }
71
72 // Copy and move not allowed
73 LoopThread(const LoopThread&) = delete;
75 LoopThread& operator=(const LoopThread&) = delete;
77
80 void start() {
81 while (!m_started) {
82 std::this_thread::sleep_for(std::chrono::milliseconds(3));
83 m_cond.notify_one();
84 }
85 }
86
88 void stop() {
89 m_keepRunning=false;
90 m_cond.notify_all();
91 }
92
94 void wait() {
95 // Nothing to do if thread already finished
96 if (m_thread==nullptr || !m_thread->joinable()) {return;}
97 // Keep notifying the condition until the loop finishes
98 while (!m_finished) {
99 std::this_thread::sleep_for(std::chrono::milliseconds(3));
100 m_cond.notify_all();
101 }
102 // Wait for the thread to return
103 m_thread->join();
104 }
105
106 std::condition_variable& cond() {return m_cond;}
107 std::mutex& mutex() {return m_mutex;}
108 };
109} // namespace HLT
110
111#endif // TRIGSERVICES_EVENTLOOPUTILS_H
std::unique_ptr< std::thread > m_thread
The thread object.
void run()
Main function executed by the thread.
std::atomic< bool > m_started
Flag whether the main loop of the thread has started and will listen to further notifications.
void waitForCond(std::unique_lock< std::mutex > &lock)
Helper to wait for the condition.
void wait()
Wait until main loop finishes.
std::condition_variable m_cond
Condition for which the thread waits most of its lifetime.
void start()
Keep notifying the thread until the callback is called for the first time (returns just before callin...
std::atomic< bool > m_keepRunning
The thread's inner while-loop condition variable.
LoopThread(LoopThread &&)=delete
LoopThread & operator=(const LoopThread &)=delete
std::mutex m_mutex
Mutex used to notify the condition.
LoopThread(const LoopThread &)=delete
std::mutex & mutex()
LoopThread & operator=(LoopThread &&)=delete
std::function< void()> m_callback
The callback executed in each step of the thread's inner while-loop.
void stop()
Flag the main loop to finish.
int m_callbackIntervalMilliseconds
If positive, call the callback periodically with this interval regardless of the m_cond.
std::condition_variable & cond()
LoopThread(std::function< void()> &&callback, int callbackInterval=-1)
std::atomic< bool > m_finished
Flag whether the main loop of the thread has finished.
It used to be useful piece of code for replacing actual SG with other store of similar functionality ...
STL namespace.