#20_BasicTaskScheduler0 基本任务调度类基类(二)——Live555源码阅读(一)任务调度相关类
这是Live555源码阅读的第二部分,包括了任务调度相关的三个类。任务调度是Live555源码中很重要的部分。
本文由乌合之众 lym瞎编,欢迎转载 my.oschina.net/oloroso
##scheduleDelayedTask方法(调度延时任务)
scheduleDelayedTask方法有三个参数,分别是时间microseconds,任务proc,数据clientData。 其使用这三个参数创建一个定时处理程序对象AlarmHandler(proc, clientData, timeToDelay),并将这个对象添加到延时队列链表中管理起来。返回了一个这个对象的唯一标识token。
1TaskToken BasicTaskScheduler0::scheduleDelayedTask(int64_t microseconds, 2 TaskFunc* proc, 3 void* clientData) { 4 if (microseconds < 0) microseconds = 0; 5 DelayInterval timeToDelay((long)(microseconds/1000000), (long)(microseconds%1000000)); 6 AlarmHandler* alarmHandler = new AlarmHandler(proc, clientData, timeToDelay); 7 fDelayQueue.addEntry(alarmHandler); 8 9 return (void*)(alarmHandler->token()); 10} 11unscheduleDelayedTask方法(取消调度延时任务) 12unscheduleDelayedTask方法将pervTask代表的节点从延时队列中移除,并销毁。参数类型TaskToKen实质是一个void*型。其应该传入的是一个AlarmHandler对象的token标识。 13void BasicTaskScheduler0::unscheduleDelayedTask(TaskToken& prevTask) { 14 DelayQueueEntry* alarmHandler = fDelayQueue.removeEntry((intptr_t)prevTask); 15 prevTask = NULL; 16 delete alarmHandler; 17}
##doEventLoop方法(事件处理循环)
这是一个死循环,在符合条件的时候,会不断调用SingleStep。这个方法是做一次事件轮询处理。参数watchVariable是用来控制是否继续循环的,如果它指向的地址的内容不是’\0’,那么就会跳出死循环,不再继续。 SingleStep在派生类BasicTaskScheduler中实现。
1void BasicTaskScheduler0::doEventLoop(char* watchVariable) { 2 // Repeatedly loop, handling readble sockets and timed events: 3 // 反复循环,可读取套接字和定时事件的处理: 4 while (1) { 5 if (watchVariable != NULL && *watchVariable != 0) break; 6 SingleStep(); 7 } 8}
##createEventTrigger方法(创建事件触发器) 这个方法将参数eventHandlerProc在数组fTriggeredEventHandlers还有空位的时候将其添加到数组中,然后返回一个指示其被添加到数组fTriggeredEventHandlers中的位置的的变量。
1EventTriggerId BasicTaskScheduler0::createEventTrigger(TaskFunc* eventHandlerProc) { 2 unsigned i = fLastUsedTriggerNum; //最后使用的触发器在数组的下标 3 EventTriggerId mask = fLastUsedTriggerMask; //bit位置 4 5 do { 6 i = (i + 1) % MAX_NUM_EVENT_TRIGGERS; //0-31之间 7 mask >>= 1; //向左移位,与下标同步 8 if (mask == 0) mask = 0x80000000; 9 //找到一个未使用的位置,就将事件处理程序地址保存到此处 10 if (fTriggeredEventHandlers[i] == NULL) { 11 // This trigger number is free; use it: 12 fTriggeredEventHandlers[i] = eventHandlerProc; 13 fTriggeredEventClientDatas[i] = NULL; // sanity 14 //更新这两个至 15 fLastUsedTriggerMask = mask; 16 fLastUsedTriggerNum = i; 17 //这个返回值可以求得上面的数组位置值 18 return mask; 19 } 20 } while (i != fLastUsedTriggerNum); 21 22 // All available event triggers are allocated; return 0 instead: 23 // 所有可用的事件触发都被分配;而返回0: 24 return 0; 25}
##deleteEventTrigger方法(删除事件触发器)
deleteEventTrigger方法将eventTriggerId标识的(非0位置)触发器从数组fTriggeredEventHandlers中移除。 fTriggersAwaitingHandling在triggeredEvent方法中修改了。
1void BasicTaskScheduler0::deleteEventTrigger(EventTriggerId eventTriggerId) { 2 //fTriggersAwaitingHandling是等待触发处理位标识(标识数组fTriggeredEventHandlers已使用) 3 //那么这儿很好理解,就是eventTriggerId中不为0的位,在对应的fTriggersAwaitingHandling中清零 4 //相当于是标识fTriggeredEventHandlers相应的位置已经被释放了。 5 fTriggersAwaitingHandling &= ~eventTriggerId; 6 7 if (eventTriggerId == fLastUsedTriggerMask) { // common-case optimization: 8 fTriggeredEventHandlers[fLastUsedTriggerNum] = NULL; 9 fTriggeredEventClientDatas[fLastUsedTriggerNum] = NULL; 10 } 11 else { 12 // "eventTriggerId" should have just one bit set.其可能是一个集合(要删除多个触发器) 13 // However, we do the reasonable thing if the user happened to 'or' together two or more "EventTriggerId"s: 14 //从将数组对应的位置清零 15 EventTriggerId mask = 0x80000000; 16 for (unsigned i = 0; i < MAX_NUM_EVENT_TRIGGERS; ++i) { 17 if ((eventTriggerId&mask) != 0) { 18 fTriggeredEventHandlers[i] = NULL; 19 fTriggeredEventClientDatas[i] = NULL; 20 } 21 mask >>= 1; 22 } 23 } 24} 25
##triggerEvent方法(触发事件)
triggerEvent并没有真正的触发事件,而是将参数eventTriggerId标识的位置,在fTriggeredEventClientDatas数组中对应的元素的值改为clientData。 之前创建触发器的时候,将fTriggeredEventClientDatas数组的对应位置是置为NULL的。
1void BasicTaskScheduler0::triggerEvent(EventTriggerId eventTriggerId, void* clientData) { 2 // First, record the "clientData":首先,记录“客户端数据”: 3 if (eventTriggerId == fLastUsedTriggerMask) { // common-case optimization: 4 fTriggeredEventClientDatas[fLastUsedTriggerNum] = clientData; 5 } 6 else { 7 EventTriggerId mask = 0x80000000; 8 for (unsigned i = 0; i < MAX_NUM_EVENT_TRIGGERS; ++i) { 9 if ((eventTriggerId&mask) != 0) { 10 fTriggeredEventClientDatas[i] = clientData; 11 12 fLastUsedTriggerMask = mask; 13 fLastUsedTriggerNum = i; 14 } 15 mask >>= 1; 16 } 17 } 18 19 // Then, note this event as being ready to be handled. 20 // (Note that because this function (unlike others in the library) can be called from an external thread, we do this last, to 21 // reduce the risk of a race condition.) 22 // 将fTriggersAwaitingHandling中对应的位置1。 23 fTriggersAwaitingHandling |= eventTriggerId; 24}
