00001 #ifndef PLATFORM_APERIOS
00002 #include "PollThread.h"
00003 #include <errno.h>
00004 #include <signal.h>
00005
00006
00007 using namespace std;
00008
00009 void PollThread::start() {
00010 launching=initialPoll=true;
00011 startTime.Set();
00012 Thread::start();
00013 }
00014
00015 void PollThread::stop() {
00016 Thread::stop();
00017 interrupt();
00018 }
00019
00020 void PollThread::interrupt() {
00021 if(launching)
00022 return;
00023 if(signal(SIGALRM,handleInterrupt)==SIG_ERR)
00024 perror("PollThread::run(): initial signal()");
00025 sendSignal(SIGALRM);
00026 }
00027
00028 bool PollThread::poll() {
00029 unsigned int sleeptime=runloop();
00030 if(sleeptime==-1U)
00031 return false;
00032 period.Set(static_cast<long>(sleeptime));
00033 return true;
00034 }
00035
00036 void PollThread::interrupted() {
00037 if(!initialPoll) {
00038 if(period-startTime.Age()<1L) {
00039 delay=0L;
00040 } else {
00041 while(!(period-startTime.Age()<1L))
00042 startTime-=period;
00043 startTime+=period;
00044 delay=period;
00045 }
00046 }
00047 }
00048
00049 void * PollThread::run() {
00050 launching=false;
00051 timespec sleepSpec,remainSpec;
00052 if(startTime.Age()<delay) {
00053 sleepSpec=delay-startTime.Age();
00054 while(nanosleep(&sleepSpec,&remainSpec)) {
00055 if(errno!=EINTR) {
00056 perror("PollThread::run(): initial nanosleep");
00057 break;
00058 }
00059
00060 if(delay<1L || delay<startTime.Age())
00061 break;
00062 sleepSpec=delay-startTime.Age();
00063 }
00064 }
00065 testCancel();
00066 if(!poll())
00067 return returnValue;
00068 initialPoll=false;
00069 bool wasInterrupted=true;
00070 for(;;) {
00071 bool noSleep=false;
00072 if(TimeET(0,0)<period) {
00073 if(trackPollTime) {
00074 if(wasInterrupted) {
00075 if(delay<0L || startTime.Age()<delay) {}
00076 else
00077 startTime+=delay;
00078 } else {
00079 if(startTime.Age()<period) {}
00080 else
00081 startTime+=period;
00082 }
00083
00084
00085
00086 if(period<startTime.Age()) {
00087 noSleep=true;
00088 while(period<startTime.Age())
00089 startTime+=period;
00090 startTime-=period;
00091 }
00092 sleepSpec=period-startTime.Age();
00093 } else {
00094 sleepSpec=period;
00095 startTime.Set();
00096 }
00097 wasInterrupted=false;
00098 while(!noSleep && nanosleep(&sleepSpec,&remainSpec)) {
00099 wasInterrupted=true;
00100 if(errno!=EINTR) {
00101 perror("PollThread::run(): periodic nanosleep");
00102 break;
00103 }
00104
00105 if(delay<1L || delay<startTime.Age())
00106 break;
00107 sleepSpec=delay-startTime.Age();
00108 }
00109 } else {
00110 startTime.Set();
00111 }
00112 testCancel();
00113 if(!poll())
00114 return returnValue;
00115 }
00116
00117 return returnValue;
00118 }
00119
00120
00121
00122
00123
00124
00125 void PollThread::handleInterrupt(int ) {
00126 if(signal(SIGALRM,SIG_DFL)==SIG_ERR)
00127 perror("PollThread::handleInterrupt(): could not re-enable signal");
00128 PollThread * cur=dynamic_cast<PollThread*>(Thread::getCurrent());
00129 if(cur==NULL) {
00130 std::cerr << "PollThread::handleInterrupt called from non-PollThread" << endl;
00131 return;
00132 }
00133 if(cur->noCancelDepth==0)
00134 cur->testCancel();
00135 cur->interrupted();
00136 }
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 #endif