Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

PollThread.cc

Go to the documentation of this file.
00001 #ifndef PLATFORM_APERIOS
00002 #include "PollThread.h"
00003 #include <stdio.h>
00004 #include <errno.h>
00005 #include <signal.h>
00006 
00007 //better to put this here instead of the header
00008 using namespace std; 
00009 
00010 void PollThread::start() {
00011   initialPoll=true;
00012   startTime.Set();
00013   Thread::start();
00014 }
00015 
00016 bool PollThread::poll() {
00017   unsigned int sleeptime=runloop();
00018   if(sleeptime==-1U)
00019     return false;
00020   period.Set(static_cast<long>(sleeptime));
00021   return true;
00022 }
00023 
00024 void PollThread::interrupted() {
00025   if(!initialPoll) {
00026     if(period-startTime.Age()<1L) {
00027       delay=0L;
00028     } else {
00029       while(!(period-startTime.Age()<1L))
00030         startTime-=period;
00031       startTime+=period;
00032       delay=period;
00033     }
00034   }
00035 }
00036 
00037 void * PollThread::run() {
00038   timespec sleepSpec,remainSpec;
00039   TimeET age = startTime.Age();
00040   if(age<delay) {
00041     sleepSpec=delay-age;
00042     while(nanosleep(&sleepSpec,&remainSpec)) {
00043       if(errno!=EINTR) {
00044         if(errno==EINVAL)
00045           std::cerr << "Invalid PollThread periodic sleep time, age=" << startTime.Age() << " period=" << period << ", delay=" << delay << " sleepSpec=" << sleepSpec.tv_sec << ' ' << sleepSpec.tv_nsec << std::endl;
00046         else
00047           perror("PollThread::run(): initial nanosleep");
00048         break;
00049       }
00050       testCancel();
00051       //interrupted() may have changed delay to indicate remaining sleep time
00052       age = startTime.Age();
00053       if(delay<1L || delay<age)
00054         break;
00055       sleepSpec=delay-age;
00056     }
00057   }
00058   testCancel();
00059   if(!poll())
00060     return returnValue;
00061   initialPoll=false;
00062   bool wasInterrupted=true; // need to add delay instead of period for the first time, same as if an interrupt occurred
00063   for(;;) {
00064     bool noSleep=false;
00065     if(TimeET(0,0)<period) {
00066       if(trackPollTime) {
00067         if(wasInterrupted) {
00068           if(delay<0L || startTime.Age()<delay) {}
00069           else
00070             startTime+=delay;
00071         } else {
00072           if(startTime.Age()<period) {}
00073           else
00074             startTime+=period;
00075         }
00076         //the idea with this part is that if we get behind, (because of poll() taking longer than period)
00077         // then we want to quick poll again as fast as we can to catch up, but we don't want to backlog
00078         // such that we'll be quick-calling multiple times once we do catch up
00079         if(period<startTime.Age()) {
00080           noSleep=true;
00081           while(period<startTime.Age())
00082             startTime+=period;
00083           startTime-=period; //back off one -- the amount we've overshot counts towards the next period
00084         }
00085         age = startTime.Age();
00086         if(age<period)
00087           sleepSpec=period-age;
00088         else
00089           noSleep=true;
00090       } else {
00091         sleepSpec=period;
00092         startTime.Set();
00093       }
00094       wasInterrupted=false;
00095       while(!noSleep && nanosleep(&sleepSpec,&remainSpec)) {
00096         wasInterrupted=true;
00097         if(errno!=EINTR) {
00098           if(errno==EINVAL)
00099             std::cerr << "Invalid PollThread periodic sleep time, age=" << startTime.Age() << " period=" << period << ", delay=" << delay << " sleepSpec=" << sleepSpec.tv_sec << ' ' << sleepSpec.tv_nsec << std::endl;
00100           else
00101             perror("PollThread::run(): periodic nanosleep");
00102           break;
00103         }
00104         testCancel();
00105         //interrupted() should have changed delay and/or period to indicate remaining sleep time
00106         age = startTime.Age();
00107         if(delay<1L || delay<age)
00108           break;
00109         sleepSpec=delay-age;
00110       }
00111     } else {
00112       startTime.Set();
00113     }
00114     testCancel();
00115     if(!poll())
00116       return returnValue;
00117   }
00118   // this return is just to satisfy warnings with silly compiler
00119   return returnValue; //never happens -- cancel or bad poll would exit
00120 }
00121 
00122 //void PollThread::cancelled() {
00123   //signal handlers are global, not per-thread, so if we reset the handler, then the next interrupt will cause the program to end :(
00124   //signal(SIGALRM,SIG_DFL);
00125 //}
00126 
00127 
00128 
00129 /*! @file
00130  * @brief 
00131  * @author Ethan Tira-Thompson (ejt) (Creator)
00132  */
00133 #endif

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