Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

FailsafeThread.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_FailsafeThread_h_
00003 #define INCLUDED_FailsafeThread_h_
00004 
00005 #include "Shared/TimeET.h"
00006 
00007 //! Enforces a timeout on another thread
00008 /*! The target thread needs to either complete execution or set the progressFlag to 'true'
00009  *  within the specified timeout period.  If the progressFlag is set, it will be cleared at the
00010  *  end of the timeout, thus requiring the target to re-set within the next timeout period. */
00011 class FailsafeThread : public Thread {
00012 public:
00013   //! constructor, specify target thread, timeout period, and optionally whether to start now
00014   FailsafeThread(Thread& th, const TimeET& delayTime, bool autostart=false)
00015   : Thread(), restartFlag(false), progressFlag(false), delay(useconds_t(delayTime.Value()*1000000)), engageFunc(&Thread::stop), target(th), engaged(false) { if(autostart) start(); }
00016   
00017   //! if set to true, the failsafe thread will restart the target if it times out instead of just stopping it
00018   volatile bool restartFlag;
00019   
00020   //! should be set by target thread if it's still making progress and wants another #delay
00021   volatile bool progressFlag;
00022   
00023   //! microseconds to wait between checks on #progressFlag
00024   /*! Changing this value won't change the @e current timeout period.  You would need to stop and
00025    *  restart the thread for a change to immediately take effect. */
00026   volatile useconds_t delay;
00027   
00028   //! the function to call on the target thread, defaults to Thread::stop, but Thread::interrupt may be useful
00029   Thread& (Thread::*engageFunc)();
00030     
00031   //! returns true if the FailsafeThread is waiting for the target to stop running
00032   /*! This is useful for the target thread to check whether it is being stopped from a timeout
00033    *  (in which case isEngaged() will return true), or if it has been stopped for some other reason. */
00034   bool isEngaged() const { return engaged; }
00035   
00036 protected:
00037   virtual unsigned int runloop() {
00038     engaged=false;
00039     // sleep as long as progress is being made
00040     usleep(delay);
00041     testCancel();
00042     while(progressFlag) {
00043       progressFlag=false;
00044       usleep(delay);
00045       testCancel();
00046     }
00047     // no more progress -- is the thread still running?
00048     if(!target.isStarted())
00049       return -1U; // no, go away
00050     // yes, stop it
00051     //std::cout << "failsafe engaged" << std::endl;
00052     engaged=true;
00053     (target.*engageFunc)();
00054     // we killed it... restart it?
00055     if(!restartFlag)
00056       return -1U; // no, go away
00057     // yes, wait for stop to go through, then start it again
00058     target.join();
00059     if(!restartFlag) // check again just in case restart was changed while waiting for join()
00060       return -1U;
00061     testCancel();
00062     target.start();
00063     engaged=false;
00064     return 0;
00065   }
00066   
00067   //virtual void cancelled() { engaged=false; }
00068   
00069   //! the thread being monitored (or at least the one that will be stopped if progressFlag isn't set)
00070   Thread& target;
00071   
00072   //! set to true when FailsafeThread is in the process of stopping (and possibly restarting) the target thread
00073   bool engaged;
00074 };
00075 
00076 
00077 /*! @file
00078  * @brief Describes FailsafeThread, which enforces a timeout on another thread
00079  * @author Ethan Tira-Thompson (ejt) (Creator)
00080  */
00081 
00082 #endif

Tekkotsu v5.1CVS
Generated Fri Mar 16 05:26:38 2012 by Doxygen 1.6.3