| # Gaudi Framework, version v21r9 |

Home |  | Generated: 3 May 2010

# WatchdogThread.cpp

Go to the documentation of this file.

    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 }