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