The Gaudi Framework  v30r3 (a5ef0a68)
WatchdogThread.cpp
Go to the documentation of this file.
1 /*
2  * Implementation of the class WatchdogThread.
3  */
4 
6 #include "GaudiKernel/Sleep.h"
7 
8 #include <functional>
9 
10 #include <boost/thread/thread.hpp>
11 
12 WatchdogThread::WatchdogThread( boost::posix_time::time_duration timeout, bool autostart )
13  : m_timeout( std::move( timeout ) ), m_running( false )
14 {
15  // Start the thread immediately if requested.
16  if ( autostart ) start();
17 }
18 
20 {
21  // Make sure the thread is stopped before exiting.
22  stop();
23 }
24 
26 {
27  if ( !m_thread ) { // can be started only if the thread is not yet started
28  m_running = true;
29  // call user-defined function
30  onStart();
31  // Initialize the first "last ping"
32  ping();
33  // Start a new thread telling it to call the member function i_run()
34  m_thread = std::make_unique<boost::thread>( std::mem_fn( &WatchdogThread::i_run ), this );
35  }
36 }
37 
39 {
40  if ( m_thread ) {
41  m_running = false; // mark the thread as stopped (interrupt doesn't work if the thread is not sleeping)
42  Gaudi::NanoSleep( 1000000 ); // Wait a bit (1ms) to be sure that the interrupt happens during the sleep
43  m_thread->interrupt(); // tell the thread to stop (if it is waiting)
44  m_thread->join(); // wait for it
45  m_thread.reset(); // delete it
46  // call user-defined function
47  onStop();
48  }
49 }
50 
52 {
53  // Copy of the last ping
54  boost::system_time lastPing = getLastPing();
55 
56  // set initial check time
57  boost::system_time nextCheck = lastPing + getTimeout();
58 
59  try {
60  // enter infinite loop
61  while ( m_running ) {
62  // Wait until the next check point time is reached.
63  // An early exit must be triggered by a call to this->interrupt(), which
64  // will produce an exception during the sleep.
65  boost::thread::sleep( nextCheck );
66  // Check if there was a ping while we were sleeping
67  if ( lastPing == getLastPing() ) { // no further accesses
68  action();
69  // schedule the next check for now + dt (seems a good estimate)
70  nextCheck = boost::get_system_time() + getTimeout();
71  } else { // there was a ping
72  // schedule the next check for last_access + dt
73  nextCheck = lastPing = getLastPing();
74  nextCheck += getTimeout();
75  }
76  }
77  }
78  // Ignore the exception since it is used only to exit from the loop.
79  catch ( boost::thread_interrupted& ) {
80  }
81 }
82 
83 // Default implementation: empty
85 
86 // Default implementation: empty
88 
89 // Default implementation: empty
91 
92 // Default implementation: empty
boost::posix_time::time_duration getTimeout() const
Get the current time-out value.
void start()
Start the watchdog thread.
virtual void onStop()
User implemented function that will be called when stopping.
STL namespace.
GAUDI_API void NanoSleep(long long nsec)
Small variation on the sleep function for nanoseconds sleep.
Definition: Sleep.cpp:10
void ping()
Function to call to notify the watchdog thread that we are still alive.
virtual ~WatchdogThread()
Destructor.
T reset(T...args)
bool m_running
Flag to mark the thread as running/stopped (avoid possible race conditions).
virtual void onPing()
User implemented function that will be called when ping is called.
void stop()
Signal the watchdog thread to stop and wait for it.
T mem_fn(T...args)
virtual void action()
User implemented function that will be called if the time-out is reached.
WatchdogThread(boost::posix_time::time_duration timeout, bool autostart=false)
Constructor.
void i_run()
Core function of the secondary thread.
std::unique_ptr< boost::thread > m_thread
Pointer to the running thread;.
boost::system_time getLastPing() const
Get the time of latest ping.
virtual void onStart()
User implemented function that will be called when starting.