The Gaudi Framework  v32r2 (46d42edc)
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  // Start the thread immediately if requested.
15  if ( autostart ) start();
16 }
17 
19  // Make sure the thread is stopped before exiting.
20  stop();
21 }
22 
24  if ( !m_thread ) { // can be started only if the thread is not yet started
25  m_running = true;
26  // call user-defined function
27  onStart();
28  // Initialize the first "last ping"
29  ping();
30  // Start a new thread telling it to call the member function i_run()
31  m_thread = std::make_unique<boost::thread>( std::mem_fn( &WatchdogThread::i_run ), this );
32  }
33 }
34 
36  if ( m_thread ) {
37  m_running = false; // mark the thread as stopped (interrupt doesn't work if the thread is not sleeping)
38  Gaudi::NanoSleep( 1000000 ); // Wait a bit (1ms) to be sure that the interrupt happens during the sleep
39  m_thread->interrupt(); // tell the thread to stop (if it is waiting)
40  m_thread->join(); // wait for it
41  m_thread.reset(); // delete it
42  // call user-defined function
43  onStop();
44  }
45 }
46 
48  // Copy of the last ping
49  boost::system_time lastPing = getLastPing();
50 
51  // set initial check time
52  boost::system_time nextCheck = lastPing + getTimeout();
53 
54  try {
55  // enter infinite loop
56  while ( m_running ) {
57  // Wait until the next check point time is reached.
58  // An early exit must be triggered by a call to this->interrupt(), which
59  // will produce an exception during the sleep.
60  boost::thread::sleep( nextCheck );
61  // Check if there was a ping while we were sleeping
62  if ( lastPing == getLastPing() ) { // no further accesses
63  action();
64  // schedule the next check for now + dt (seems a good estimate)
65  nextCheck = boost::get_system_time() + getTimeout();
66  } else { // there was a ping
67  // schedule the next check for last_access + dt
68  nextCheck = lastPing = getLastPing();
69  nextCheck += getTimeout();
70  }
71  }
72  }
73  // Ignore the exception since it is used only to exit from the loop.
74  catch ( boost::thread_interrupted& ) {}
75 }
76 
77 // Default implementation: empty
79 
80 // Default implementation: empty
82 
83 // Default implementation: empty
85 
86 // Default implementation: empty
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:9
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.
boost::system_time getLastPing() const
Get the time of latest ping.
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::posix_time::time_duration getTimeout() const
Get the current time-out value.
virtual void onStart()
User implemented function that will be called when starting.