|
Gaudi Framework, version v23r2 |
| Home | Generated: Thu Jun 28 2012 |
00001 /* 00002 * Implementation of the class WatchdogThread. 00003 */ 00004 00005 #include "GaudiKernel/WatchdogThread.h" 00006 #include "GaudiKernel/Sleep.h" 00007 00008 #include <functional> 00009 00010 #include <boost/thread/thread.hpp> 00011 00012 WatchdogThread::WatchdogThread(boost::posix_time::time_duration timeout, bool autostart): 00013 m_timeout(timeout), m_running(false) 00014 { 00015 // Start the thread immediately if requested. 00016 if (autostart) start(); 00017 } 00018 00019 WatchdogThread::~WatchdogThread() { 00020 // Make sure the thread is stopped before exiting. 00021 stop(); 00022 } 00023 00024 void WatchdogThread::start() { 00025 if (!m_thread.get()) { // can be started only if the thread is not yet started 00026 m_running = true; 00027 // call user-defined function 00028 onStart(); 00029 // Initialize the first "last ping" 00030 ping(); 00031 // Start a new thread telling it to call the member function i_run() 00032 m_thread = std::auto_ptr<boost::thread>(new boost::thread(std::mem_fun(&WatchdogThread::i_run), this)); 00033 } 00034 } 00035 00036 void WatchdogThread::stop() { 00037 if (m_thread.get()) { 00038 m_running = false; // mark the thread as stopped (interrupt doesn't work if the thread is not sleeping) 00039 Gaudi::NanoSleep(1000000); // Wait a bit (1ms) to be sure that the interrupt happens during the sleep 00040 m_thread->interrupt(); // tell the thread to stop (if it is waiting) 00041 m_thread->join(); // wait for it 00042 m_thread.reset(); // delete it 00043 // call user-defined function 00044 onStop(); 00045 } 00046 } 00047 00048 void WatchdogThread::i_run() { 00049 // Copy of the last ping 00050 boost::system_time lastPing = getLastPing(); 00051 00052 // set initial check time 00053 boost::system_time nextCheck = lastPing + getTimeout(); 00054 00055 try { 00056 // enter infinite loop 00057 while (m_running) { 00058 // Wait until the next check point time is reached. 00059 // An early exit must be triggered by a call to this->interrupt(), which 00060 // will produce an exception during the sleep. 00061 boost::thread::sleep(nextCheck); 00062 // Check if there was a ping while we were sleeping 00063 if ( lastPing == getLastPing() ) { // no further accesses 00064 action(); 00065 // schedule the next check for now + dt (seems a good estimate) 00066 nextCheck = boost::get_system_time() + getTimeout(); 00067 } else { // there was a ping 00068 // schedule the next check for last_access + dt 00069 nextCheck = lastPing = getLastPing(); 00070 nextCheck += getTimeout(); 00071 } 00072 } 00073 } 00074 // Ignore the exception since it is used only to exit from the loop. 00075 catch (boost::thread_interrupted&) {} 00076 } 00077 00078 // Default implementation: empty 00079 void WatchdogThread::action() { 00080 } 00081 00082 // Default implementation: empty 00083 void WatchdogThread::onPing() { 00084 } 00085 00086 // Default implementation: empty 00087 void WatchdogThread::onStart() { 00088 } 00089 00090 // Default implementation: empty 00091 void WatchdogThread::onStop() { 00092 }