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

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:38 2016 by Doxygen 1.6.3