BasicUsageEnvironment/BasicTaskScheduler0.cpp

Go to the documentation of this file.
00001 /**********
00002 This library is free software; you can redistribute it and/or modify it under
00003 the terms of the GNU Lesser General Public License as published by the
00004 Free Software Foundation; either version 2.1 of the License, or (at your
00005 option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
00006 
00007 This library is distributed in the hope that it will be useful, but WITHOUT
00008 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00009 FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
00010 more details.
00011 
00012 You should have received a copy of the GNU Lesser General Public License
00013 along with this library; if not, write to the Free Software Foundation, Inc.,
00014 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
00015 **********/
00016 // Copyright (c) 1996-2012 Live Networks, Inc.  All rights reserved.
00017 // Basic Usage Environment: for a simple, non-scripted, console application
00018 // Implementation
00019 
00020 #include "BasicUsageEnvironment0.hh"
00021 #include "HandlerSet.hh"
00022 
00025 
00026 class AlarmHandler: public DelayQueueEntry {
00027 public:
00028   AlarmHandler(TaskFunc* proc, void* clientData, DelayInterval timeToDelay)
00029     : DelayQueueEntry(timeToDelay), fProc(proc), fClientData(clientData) {
00030   }
00031 
00032 private: // redefined virtual functions
00033   virtual void handleTimeout() {
00034     (*fProc)(fClientData);
00035     DelayQueueEntry::handleTimeout();
00036   }
00037 
00038 private:
00039   TaskFunc* fProc;
00040   void* fClientData;
00041 };
00042 
00043 
00045 
00046 BasicTaskScheduler0::BasicTaskScheduler0()
00047   : fLastHandledSocketNum(-1), fTriggersAwaitingHandling(0), fLastUsedTriggerMask(1), fLastUsedTriggerNum(MAX_NUM_EVENT_TRIGGERS-1) {
00048   fHandlers = new HandlerSet;
00049   for (unsigned i = 0; i < MAX_NUM_EVENT_TRIGGERS; ++i) {
00050     fTriggeredEventHandlers[i] = NULL;
00051     fTriggeredEventClientDatas[i] = NULL;
00052   }
00053 }
00054 
00055 BasicTaskScheduler0::~BasicTaskScheduler0() {
00056   delete fHandlers;
00057 }
00058 
00059 TaskToken BasicTaskScheduler0::scheduleDelayedTask(int64_t microseconds,
00060                                                  TaskFunc* proc,
00061                                                  void* clientData) {
00062   if (microseconds < 0) microseconds = 0;
00063   DelayInterval timeToDelay((long)(microseconds/1000000), (long)(microseconds%1000000));
00064   AlarmHandler* alarmHandler = new AlarmHandler(proc, clientData, timeToDelay);
00065   fDelayQueue.addEntry(alarmHandler);
00066 
00067   return (void*)(alarmHandler->token());
00068 }
00069 
00070 void BasicTaskScheduler0::unscheduleDelayedTask(TaskToken& prevTask) {
00071   DelayQueueEntry* alarmHandler = fDelayQueue.removeEntry((intptr_t)prevTask);
00072   prevTask = NULL;
00073   delete alarmHandler;
00074 }
00075 
00076 void BasicTaskScheduler0::doEventLoop(char* watchVariable) {
00077   // Repeatedly loop, handling readble sockets and timed events:
00078   while (1) {
00079     if (watchVariable != NULL && *watchVariable != 0) break;
00080     SingleStep();
00081   }
00082 }
00083 
00084 EventTriggerId BasicTaskScheduler0::createEventTrigger(TaskFunc* eventHandlerProc) {
00085   unsigned i = fLastUsedTriggerNum;
00086   EventTriggerId mask = fLastUsedTriggerMask;
00087 
00088   do {
00089     i = (i+1)%MAX_NUM_EVENT_TRIGGERS;
00090     mask >>= 1;
00091     if (mask == 0) mask = 0x80000000;
00092 
00093     if (fTriggeredEventHandlers[i] == NULL) {
00094       // This trigger number is free; use it:
00095       fTriggeredEventHandlers[i] = eventHandlerProc;
00096       fTriggeredEventClientDatas[i] = NULL; // sanity
00097 
00098       fLastUsedTriggerMask = mask;
00099       fLastUsedTriggerNum = i;
00100 
00101       return mask;
00102     }
00103   } while (i != fLastUsedTriggerNum);
00104 
00105   // All available event triggers are allocated; return 0 instead:
00106   return 0;
00107 }
00108 
00109 void BasicTaskScheduler0::deleteEventTrigger(EventTriggerId eventTriggerId) {
00110   fTriggersAwaitingHandling &=~ eventTriggerId;
00111 
00112   if (eventTriggerId == fLastUsedTriggerMask) { // common-case optimization:
00113     fTriggeredEventHandlers[fLastUsedTriggerNum] = NULL;
00114     fTriggeredEventClientDatas[fLastUsedTriggerNum] = NULL;
00115   } else {
00116     // "eventTriggerId" should have just one bit set.
00117     // However, we do the reasonable thing if the user happened to 'or' together two or more "EventTriggerId"s:
00118     EventTriggerId mask = 0x80000000;
00119     for (unsigned i = 0; i < MAX_NUM_EVENT_TRIGGERS; ++i) {
00120       if ((eventTriggerId&mask) != 0) {
00121         fTriggeredEventHandlers[i] = NULL;
00122         fTriggeredEventClientDatas[i] = NULL;
00123       }
00124       mask >>= 1;
00125     }
00126   }
00127 }
00128 
00129 void BasicTaskScheduler0::triggerEvent(EventTriggerId eventTriggerId, void* clientData) {
00130   // First, record the "clientData":
00131   if (eventTriggerId == fLastUsedTriggerMask) { // common-case optimization:
00132     fTriggeredEventClientDatas[fLastUsedTriggerNum] = clientData;
00133   } else {
00134     EventTriggerId mask = 0x80000000;
00135     for (unsigned i = 0; i < MAX_NUM_EVENT_TRIGGERS; ++i) {
00136       if ((eventTriggerId&mask) != 0) {
00137         fTriggeredEventClientDatas[i] = clientData;
00138 
00139         fLastUsedTriggerMask = mask;
00140         fLastUsedTriggerNum = i;
00141       }
00142       mask >>= 1;
00143     }
00144   }
00145 
00146   // Then, note this event as being ready to be handled.
00147   // (Note that because this function (unlike others in the library) can be called from an external thread, we do this last, to
00148   //  reduce the risk of a race condition.)
00149   fTriggersAwaitingHandling |= eventTriggerId;
00150 }
00151 
00152 
00154 
00155 HandlerDescriptor::HandlerDescriptor(HandlerDescriptor* nextHandler)
00156   : conditionSet(0), handlerProc(NULL) {
00157   // Link this descriptor into a doubly-linked list:
00158   if (nextHandler == this) { // initialization
00159     fNextHandler = fPrevHandler = this;
00160   } else {
00161     fNextHandler = nextHandler;
00162     fPrevHandler = nextHandler->fPrevHandler;
00163     nextHandler->fPrevHandler = this;
00164     fPrevHandler->fNextHandler = this;
00165   }
00166 }
00167 
00168 HandlerDescriptor::~HandlerDescriptor() {
00169   // Unlink this descriptor from a doubly-linked list:
00170   fNextHandler->fPrevHandler = fPrevHandler;
00171   fPrevHandler->fNextHandler = fNextHandler;
00172 }
00173 
00174 HandlerSet::HandlerSet()
00175   : fHandlers(&fHandlers) {
00176   fHandlers.socketNum = -1; // shouldn't ever get looked at, but in case...
00177 }
00178 
00179 HandlerSet::~HandlerSet() {
00180   // Delete each handler descriptor:
00181   while (fHandlers.fNextHandler != &fHandlers) {
00182     delete fHandlers.fNextHandler; // changes fHandlers->fNextHandler
00183   }
00184 }
00185 
00186 void HandlerSet
00187 ::assignHandler(int socketNum, int conditionSet, TaskScheduler::BackgroundHandlerProc* handlerProc, void* clientData) {
00188   // First, see if there's already a handler for this socket:
00189   HandlerDescriptor* handler = lookupHandler(socketNum);
00190   if (handler == NULL) { // No existing handler, so create a new descr:
00191     handler = new HandlerDescriptor(fHandlers.fNextHandler);
00192     handler->socketNum = socketNum;
00193   }
00194 
00195   handler->conditionSet = conditionSet;
00196   handler->handlerProc = handlerProc;
00197   handler->clientData = clientData;
00198 }
00199 
00200 void HandlerSet::clearHandler(int socketNum) {
00201   HandlerDescriptor* handler = lookupHandler(socketNum);
00202   delete handler;
00203 }
00204 
00205 void HandlerSet::moveHandler(int oldSocketNum, int newSocketNum) {
00206   HandlerDescriptor* handler = lookupHandler(oldSocketNum);
00207   if (handler != NULL) {
00208     handler->socketNum = newSocketNum;
00209   }
00210 }
00211 
00212 HandlerDescriptor* HandlerSet::lookupHandler(int socketNum) {
00213   HandlerDescriptor* handler;
00214   HandlerIterator iter(*this);
00215   while ((handler = iter.next()) != NULL) {
00216     if (handler->socketNum == socketNum) break;
00217   }
00218   return handler;
00219 }
00220 
00221 HandlerIterator::HandlerIterator(HandlerSet& handlerSet)
00222   : fOurSet(handlerSet) {
00223   reset();
00224 }
00225 
00226 HandlerIterator::~HandlerIterator() {
00227 }
00228 
00229 void HandlerIterator::reset() {
00230   fNextPtr = fOurSet.fHandlers.fNextHandler;
00231 }
00232 
00233 HandlerDescriptor* HandlerIterator::next() {
00234   HandlerDescriptor* result = fNextPtr;
00235   if (result == &fOurSet.fHandlers) { // no more
00236     result = NULL;
00237   } else {
00238     fNextPtr = fNextPtr->fNextHandler;
00239   }
00240 
00241   return result;
00242 }

Generated on Thu Feb 2 23:51:29 2012 for live by  doxygen 1.5.2