ATLAS Offline Software
Loading...
Searching...
No Matches
EventLoopUtils.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4#ifndef TRIGSERVICES_EVENTLOOPUTILS_H
5#define TRIGSERVICES_EVENTLOOPUTILS_H
6#include <chrono>
7#include <condition_variable>
8#include <functional>
9#include <memory>
10#include <mutex>
11#include <thread>
12
13namespace HLT {
15 class LoopThread {
16 private:
18 std::condition_variable m_cond;
20 std::mutex m_mutex;
22 bool m_keepRunning{true};
24 bool m_started{false};
26 bool m_finished{false};
28 std::function<void()> m_callback;
32 std::unique_ptr<std::thread> m_thread;
33
35 inline void waitForCond(std::unique_lock<std::mutex>& lock) {
37 m_cond.wait(lock);
38 } else {
39 m_cond.wait_for(lock, std::chrono::milliseconds(m_callbackIntervalMilliseconds));
40 }
41 }
42
44 void run() {
45 if (!m_keepRunning) {return;}
46 std::unique_lock<std::mutex> lock{m_mutex};
47
48 // first call outside the loop to set the m_started flag
49 waitForCond(lock);
50 m_started = true;
51 m_callback();
52
53 // subsequent calls in a loop
54 while(m_keepRunning) {
55 waitForCond(lock);
56 m_callback();
57 }
58 m_finished = true;
59 }
60
61 public:
62 explicit LoopThread(std::function<void()>&& callback, int callbackInterval=-1)
63 : m_callback(std::move(callback)),
64 m_callbackIntervalMilliseconds(callbackInterval),
65 m_thread(std::make_unique<std::thread>([this]{run();})) {}
66
68 wait();
69 }
70
71 // Copy and move not allowed
72 LoopThread(const LoopThread&) = delete;
74 LoopThread& operator=(const LoopThread&) = delete;
76
79 void start() {
80 while (!m_started) {
81 std::this_thread::sleep_for(std::chrono::milliseconds(3));
82 m_cond.notify_one();
83 }
84 }
85
87 void stop() {
88 m_keepRunning=false;
89 m_cond.notify_all();
90 }
91
93 void wait() {
94 // Nothing to do if thread already finished
95 if (m_thread==nullptr || !m_thread->joinable()) {return;}
96 // Keep notifying the condition until the loop finishes
97 while (!m_finished) {
98 std::this_thread::sleep_for(std::chrono::milliseconds(3));
99 m_cond.notify_all();
100 }
101 // Wait for the thread to return
102 m_thread->join();
103 }
104
105 std::condition_variable& cond() {return m_cond;}
106 std::mutex& mutex() {return m_mutex;}
107 };
108} // namespace HLT
109
110#endif // TRIGSERVICES_EVENTLOOPUTILS_H
std::unique_ptr< std::thread > m_thread
The thread object.
void run()
Main function executed by the thread.
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...
bool m_finished
Flag whether the main loop of the thread has finished.
LoopThread(LoopThread &&)=delete
LoopThread & operator=(const LoopThread &)=delete
std::mutex m_mutex
Mutex used to notify the condition.
bool m_started
Flag whether the main loop of the thread has started and will listen to further notifications.
bool m_keepRunning
The thread's inner while-loop condition variable.
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)
It used to be useful piece of code for replacing actual SG with other store of similar functionality ...
STL namespace.