ATLAS Offline Software
EventLoopUtils.h
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 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 
13 namespace HLT {
15  class LoopThread {
16  private:
18  std::condition_variable m_cond;
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  // Nothing to do if thread already finished
69  if (m_thread==nullptr || !m_thread->joinable()) {return;}
70  // Keep notifying the condition until the loop finishes
71  while (!m_finished) {
72  std::this_thread::sleep_for(std::chrono::milliseconds(3));
73  m_cond.notify_all();
74  }
75  // Wait for the thread to return
76  m_thread->join();
77  }
78 
79  // Copy and move not allowed
80  LoopThread(const LoopThread&) = delete;
81  LoopThread(LoopThread&&) = delete;
82  LoopThread& operator=(const LoopThread&) = delete;
84 
87  void start() {
88  while (!m_started) {
89  std::this_thread::sleep_for(std::chrono::milliseconds(3));
90  m_cond.notify_one();
91  }
92  }
93 
95  void stop() {
96  m_keepRunning=false;
97  m_cond.notify_all();
98  }
99 
100  std::condition_variable& cond() {return m_cond;}
101  std::mutex& mutex() {return m_mutex;}
102  };
103 } // namespace HLT
104 
105 #endif // TRIGSERVICES_EVENTLOOPUTILS_H
HLT::LoopThread::m_callback
std::function< void()> m_callback
The callback executed in each step of the thread's inner while-loop.
Definition: EventLoopUtils.h:28
HLT::LoopThread::waitForCond
void waitForCond(std::unique_lock< std::mutex > &lock)
Helper to wait for the condition.
Definition: EventLoopUtils.h:35
make_unique
std::unique_ptr< T > make_unique(Args &&... args)
Definition: SkimmingToolEXOT5.cxx:23
BeamSpot::mutex
std::mutex mutex
Definition: InDetBeamSpotVertex.cxx:18
HLT::LoopThread::LoopThread
LoopThread(const LoopThread &)=delete
HLT::LoopThread::mutex
std::mutex & mutex()
Definition: EventLoopUtils.h:101
runLayerRecalibration.callback
callback
Definition: runLayerRecalibration.py:64
HLT::LoopThread::stop
void stop()
Flag the main loop to finish.
Definition: EventLoopUtils.h:95
HLT::LoopThread::operator=
LoopThread & operator=(const LoopThread &)=delete
HLT::LoopThread::operator=
LoopThread & operator=(LoopThread &&)=delete
HLT::LoopThread::m_keepRunning
bool m_keepRunning
The thread's inner while-loop condition variable.
Definition: EventLoopUtils.h:22
HLT::LoopThread::m_finished
bool m_finished
Flag whether the main loop of the thread has finished.
Definition: EventLoopUtils.h:26
HLT
It used to be useful piece of code for replacing actual SG with other store of similar functionality ...
Definition: HLTResultReader.h:26
HLT::LoopThread
Helper class to manage a long-running thread (duration of event loop)
Definition: EventLoopUtils.h:15
HLT::LoopThread::LoopThread
LoopThread(LoopThread &&)=delete
HLT::LoopThread::start
void start()
Keep notifying the thread until the callback is called for the first time (returns just before callin...
Definition: EventLoopUtils.h:87
HLT::LoopThread::m_mutex
std::mutex m_mutex
Mutex used to notify the condition.
Definition: EventLoopUtils.h:20
HLT::LoopThread::run
void run()
Main function executed by the thread.
Definition: EventLoopUtils.h:44
HLT::LoopThread::m_started
bool m_started
Flag whether the main loop of the thread has started and will listen to further notifications.
Definition: EventLoopUtils.h:24
HLT::LoopThread::m_thread
std::unique_ptr< std::thread > m_thread
The thread object.
Definition: EventLoopUtils.h:32
HLT::LoopThread::m_callbackIntervalMilliseconds
int m_callbackIntervalMilliseconds
If positive, call the callback periodically with this interval regardless of the m_cond.
Definition: EventLoopUtils.h:30
HLT::LoopThread::LoopThread
LoopThread(std::function< void()> &&callback, int callbackInterval=-1)
Definition: EventLoopUtils.h:62
HLT::LoopThread::~LoopThread
~LoopThread()
Definition: EventLoopUtils.h:67
HLT::LoopThread::m_cond
std::condition_variable m_cond
Condition for which the thread waits most of its lifetime.
Definition: EventLoopUtils.h:18
HLT::LoopThread::cond
std::condition_variable & cond()
Definition: EventLoopUtils.h:100