00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "BasicUsageEnvironment.hh"
00022 #include "HandlerSet.hh"
00023 #include <stdio.h>
00024 #if defined(_QNX4)
00025 #include <sys/select.h>
00026 #include <unix.h>
00027 #endif
00028
00030
00031 BasicTaskScheduler* BasicTaskScheduler::createNew() {
00032 return new BasicTaskScheduler();
00033 }
00034
00035 #define MAX_SCHEDULER_GRANULARITY 10000 // 10 microseconds: We will return to the event loop at least this often
00036 static void schedulerTickTask(void* clientData) {
00037 ((BasicTaskScheduler*)clientData)->scheduleDelayedTask(MAX_SCHEDULER_GRANULARITY, schedulerTickTask, clientData);
00038 }
00039
00040 BasicTaskScheduler::BasicTaskScheduler()
00041 : fMaxNumSockets(0) {
00042 FD_ZERO(&fReadSet);
00043 FD_ZERO(&fWriteSet);
00044 FD_ZERO(&fExceptionSet);
00045
00046 schedulerTickTask(this);
00047 }
00048
00049 BasicTaskScheduler::~BasicTaskScheduler() {
00050 }
00051
00052 #ifndef MILLION
00053 #define MILLION 1000000
00054 #endif
00055
00056 void BasicTaskScheduler::SingleStep(unsigned maxDelayTime) {
00057 fd_set readSet = fReadSet;
00058 fd_set writeSet = fWriteSet;
00059 fd_set exceptionSet = fExceptionSet;
00060
00061 DelayInterval const& timeToDelay = fDelayQueue.timeToNextAlarm();
00062 struct timeval tv_timeToDelay;
00063 tv_timeToDelay.tv_sec = timeToDelay.seconds();
00064 tv_timeToDelay.tv_usec = timeToDelay.useconds();
00065
00066
00067 const long MAX_TV_SEC = MILLION;
00068 if (tv_timeToDelay.tv_sec > MAX_TV_SEC) {
00069 tv_timeToDelay.tv_sec = MAX_TV_SEC;
00070 }
00071
00072 if (maxDelayTime > 0 &&
00073 (tv_timeToDelay.tv_sec > (long)maxDelayTime/MILLION ||
00074 (tv_timeToDelay.tv_sec == (long)maxDelayTime/MILLION &&
00075 tv_timeToDelay.tv_usec > (long)maxDelayTime%MILLION))) {
00076 tv_timeToDelay.tv_sec = maxDelayTime/MILLION;
00077 tv_timeToDelay.tv_usec = maxDelayTime%MILLION;
00078 }
00079
00080 int selectResult = select(fMaxNumSockets, &readSet, &writeSet, &exceptionSet, &tv_timeToDelay);
00081 if (selectResult < 0) {
00082 #if defined(__WIN32__) || defined(_WIN32)
00083 int err = WSAGetLastError();
00084
00085
00086 if (err == WSAEINVAL && readSet.fd_count == 0) {
00087 err = EINTR;
00088
00089 int dummySocketNum = socket(AF_INET, SOCK_DGRAM, 0);
00090 FD_SET((unsigned)dummySocketNum, &fReadSet);
00091 }
00092 if (err != EINTR) {
00093 #else
00094 if (errno != EINTR && errno != EAGAIN) {
00095 #endif
00096
00097 #if !defined(_WIN32_WCE)
00098 perror("BasicTaskScheduler::SingleStep(): select() fails");
00099 #endif
00100 internalError();
00101 }
00102 }
00103
00104
00105 HandlerIterator iter(*fHandlers);
00106 HandlerDescriptor* handler;
00107
00108
00109 if (fLastHandledSocketNum >= 0) {
00110 while ((handler = iter.next()) != NULL) {
00111 if (handler->socketNum == fLastHandledSocketNum) break;
00112 }
00113 if (handler == NULL) {
00114 fLastHandledSocketNum = -1;
00115 iter.reset();
00116 }
00117 }
00118 while ((handler = iter.next()) != NULL) {
00119 int sock = handler->socketNum;
00120 int resultConditionSet = 0;
00121 if (FD_ISSET(sock, &readSet) && FD_ISSET(sock, &fReadSet)) resultConditionSet |= SOCKET_READABLE;
00122 if (FD_ISSET(sock, &writeSet) && FD_ISSET(sock, &fWriteSet)) resultConditionSet |= SOCKET_WRITABLE;
00123 if (FD_ISSET(sock, &exceptionSet) && FD_ISSET(sock, &fExceptionSet)) resultConditionSet |= SOCKET_EXCEPTION;
00124 if ((resultConditionSet&handler->conditionSet) != 0 && handler->handlerProc != NULL) {
00125 fLastHandledSocketNum = sock;
00126
00127
00128 (*handler->handlerProc)(handler->clientData, resultConditionSet);
00129 break;
00130 }
00131 }
00132 if (handler == NULL && fLastHandledSocketNum >= 0) {
00133
00134
00135 iter.reset();
00136 while ((handler = iter.next()) != NULL) {
00137 int sock = handler->socketNum;
00138 int resultConditionSet = 0;
00139 if (FD_ISSET(sock, &readSet) && FD_ISSET(sock, &fReadSet)) resultConditionSet |= SOCKET_READABLE;
00140 if (FD_ISSET(sock, &writeSet) && FD_ISSET(sock, &fWriteSet)) resultConditionSet |= SOCKET_WRITABLE;
00141 if (FD_ISSET(sock, &exceptionSet) && FD_ISSET(sock, &fExceptionSet)) resultConditionSet |= SOCKET_EXCEPTION;
00142 if ((resultConditionSet&handler->conditionSet) != 0 && handler->handlerProc != NULL) {
00143 fLastHandledSocketNum = sock;
00144
00145
00146 (*handler->handlerProc)(handler->clientData, resultConditionSet);
00147 break;
00148 }
00149 }
00150 if (handler == NULL) fLastHandledSocketNum = -1;
00151 }
00152
00153
00154
00155 if (fTriggersAwaitingHandling != 0) {
00156 if (fTriggersAwaitingHandling == fLastUsedTriggerMask) {
00157
00158 fTriggersAwaitingHandling = 0;
00159 if (fTriggeredEventHandlers[fLastUsedTriggerNum] != NULL) {
00160 (*fTriggeredEventHandlers[fLastUsedTriggerNum])(fTriggeredEventClientDatas[fLastUsedTriggerNum]);
00161 }
00162 } else {
00163
00164 unsigned i = fLastUsedTriggerNum;
00165 EventTriggerId mask = fLastUsedTriggerMask;
00166
00167 do {
00168 i = (i+1)%MAX_NUM_EVENT_TRIGGERS;
00169 mask >>= 1;
00170 if (mask == 0) mask = 0x80000000;
00171
00172 if ((fTriggersAwaitingHandling&mask) != 0) {
00173 fTriggersAwaitingHandling &=~ mask;
00174 if (fTriggeredEventHandlers[i] != NULL) {
00175 (*fTriggeredEventHandlers[i])(fTriggeredEventClientDatas[i]);
00176 }
00177
00178 fLastUsedTriggerMask = mask;
00179 fLastUsedTriggerNum = i;
00180 break;
00181 }
00182 } while (i != fLastUsedTriggerNum);
00183 }
00184 }
00185
00186
00187 fDelayQueue.handleAlarm();
00188 }
00189
00190 void BasicTaskScheduler
00191 ::setBackgroundHandling(int socketNum, int conditionSet, BackgroundHandlerProc* handlerProc, void* clientData) {
00192 if (socketNum < 0) return;
00193 FD_CLR((unsigned)socketNum, &fReadSet);
00194 FD_CLR((unsigned)socketNum, &fWriteSet);
00195 FD_CLR((unsigned)socketNum, &fExceptionSet);
00196 if (conditionSet == 0) {
00197 fHandlers->clearHandler(socketNum);
00198 if (socketNum+1 == fMaxNumSockets) {
00199 --fMaxNumSockets;
00200 }
00201 } else {
00202 fHandlers->assignHandler(socketNum, conditionSet, handlerProc, clientData);
00203 if (socketNum+1 > fMaxNumSockets) {
00204 fMaxNumSockets = socketNum+1;
00205 }
00206 if (conditionSet&SOCKET_READABLE) FD_SET((unsigned)socketNum, &fReadSet);
00207 if (conditionSet&SOCKET_WRITABLE) FD_SET((unsigned)socketNum, &fWriteSet);
00208 if (conditionSet&SOCKET_EXCEPTION) FD_SET((unsigned)socketNum, &fExceptionSet);
00209 }
00210 }
00211
00212 void BasicTaskScheduler::moveSocketHandling(int oldSocketNum, int newSocketNum) {
00213 if (oldSocketNum < 0 || newSocketNum < 0) return;
00214 if (FD_ISSET(oldSocketNum, &fReadSet)) {FD_CLR((unsigned)oldSocketNum, &fReadSet); FD_SET((unsigned)newSocketNum, &fReadSet);}
00215 if (FD_ISSET(oldSocketNum, &fWriteSet)) {FD_CLR((unsigned)oldSocketNum, &fWriteSet); FD_SET((unsigned)newSocketNum, &fWriteSet);}
00216 if (FD_ISSET(oldSocketNum, &fExceptionSet)) {FD_CLR((unsigned)oldSocketNum, &fExceptionSet); FD_SET((unsigned)newSocketNum, &fExceptionSet);}
00217 fHandlers->moveHandler(oldSocketNum, newSocketNum);
00218
00219 if (oldSocketNum+1 == fMaxNumSockets) {
00220 --fMaxNumSockets;
00221 }
00222 if (newSocketNum+1 > fMaxNumSockets) {
00223 fMaxNumSockets = newSocketNum+1;
00224 }
00225 }