博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
20 BasicTaskScheduler0 基本任务调度类基类(二)——Live555源码阅读(一)任务调度相关类...
阅读量:5216 次
发布时间:2019-06-14

本文共 4895 字,大约阅读时间需要 16 分钟。

这是Live555源码阅读的第二部分,包括了任务调度相关的三个类。任务调度是Live555源码中很重要的部分。

scheduleDelayedTask方法(调度延时任务)

scheduleDelayedTask方法有三个参数,分别是时间microseconds,任务proc,数据clientData

其使用这三个参数创建一个定时处理程序对象AlarmHandler(proc, clientData, timeToDelay),并将这个对象添加到延时队列链表中管理起来。返回了一个这个对象的唯一标识token。

TaskToken BasicTaskScheduler0::scheduleDelayedTask(int64_t microseconds,                         TaskFunc* proc,                         void* clientData) {  if (microseconds < 0) microseconds = 0;  DelayInterval timeToDelay((long)(microseconds/1000000), (long)(microseconds%1000000));  AlarmHandler* alarmHandler = new AlarmHandler(proc, clientData, timeToDelay);  fDelayQueue.addEntry(alarmHandler);  return (void*)(alarmHandler->token());}unscheduleDelayedTask方法(取消调度延时任务)unscheduleDelayedTask方法将pervTask代表的节点从延时队列中移除,并销毁。参数类型TaskToKen实质是一个void*型。其应该传入的是一个AlarmHandler对象的token标识。void BasicTaskScheduler0::unscheduleDelayedTask(TaskToken& prevTask) {  DelayQueueEntry* alarmHandler = fDelayQueue.removeEntry((intptr_t)prevTask);  prevTask = NULL;  delete alarmHandler;}

doEventLoop方法(事件处理循环)

这是一个死循环,在符合条件的时候,会不断调用SingleStep。这个方法是做一次事件轮询处理。参数watchVariable是用来控制是否继续循环的,如果它指向的地址的内容不是’\0’,那么就会跳出死循环,不再继续。

SingleStep在派生类BasicTaskScheduler中实现。

void BasicTaskScheduler0::doEventLoop(char* watchVariable) {    // Repeatedly loop, handling readble sockets and timed events:    // 反复循环,可读取套接字和定时事件的处理:    while (1) {        if (watchVariable != NULL && *watchVariable != 0) break;        SingleStep();    }}

createEventTrigger方法(创建事件触发器)

这个方法将参数eventHandlerProc在数组fTriggeredEventHandlers还有空位的时候将其添加到数组中,然后返回一个指示其被添加到数组fTriggeredEventHandlers中的位置的的变量。

EventTriggerId BasicTaskScheduler0::createEventTrigger(TaskFunc* eventHandlerProc) {    unsigned i = fLastUsedTriggerNum;   //最后使用的触发器在数组的下标    EventTriggerId mask = fLastUsedTriggerMask; //bit位置    do {        i = (i + 1) % MAX_NUM_EVENT_TRIGGERS;   //0-31之间        mask >>= 1;     //向左移位,与下标同步        if (mask == 0) mask = 0x80000000;        //找到一个未使用的位置,就将事件处理程序地址保存到此处        if (fTriggeredEventHandlers[i] == NULL) {            // This trigger number is free; use it:            fTriggeredEventHandlers[i] = eventHandlerProc;            fTriggeredEventClientDatas[i] = NULL; // sanity            //更新这两个至            fLastUsedTriggerMask = mask;            fLastUsedTriggerNum = i;            //这个返回值可以求得上面的数组位置值            return mask;        }    } while (i != fLastUsedTriggerNum);    // All available event triggers are allocated; return 0 instead:    // 所有可用的事件触发都被分配;而返回0:    return 0;}

deleteEventTrigger方法(删除事件触发器)

deleteEventTrigger方法将eventTriggerId标识的(非0位置)触发器从数组fTriggeredEventHandlers中移除。

fTriggersAwaitingHandlingtriggeredEvent方法中修改了。

void BasicTaskScheduler0::deleteEventTrigger(EventTriggerId eventTriggerId) {    //fTriggersAwaitingHandling是等待触发处理位标识(标识数组fTriggeredEventHandlers已使用)    //那么这儿很好理解,就是eventTriggerId中不为0的位,在对应的fTriggersAwaitingHandling中清零    //相当于是标识fTriggeredEventHandlers相应的位置已经被释放了。    fTriggersAwaitingHandling &= ~eventTriggerId;    if (eventTriggerId == fLastUsedTriggerMask) { // common-case optimization:        fTriggeredEventHandlers[fLastUsedTriggerNum] = NULL;        fTriggeredEventClientDatas[fLastUsedTriggerNum] = NULL;    }    else {        // "eventTriggerId" should have just one bit set.其可能是一个集合(要删除多个触发器)        // However, we do the reasonable thing if the user happened to 'or' together two or more "EventTriggerId"s:        //从将数组对应的位置清零        EventTriggerId mask = 0x80000000;        for (unsigned i = 0; i < MAX_NUM_EVENT_TRIGGERS; ++i) {            if ((eventTriggerId&mask) != 0) {                fTriggeredEventHandlers[i] = NULL;                fTriggeredEventClientDatas[i] = NULL;            }            mask >>= 1;        }    }}

triggerEvent方法(触发事件)

triggerEvent并没有真正的触发事件,而是将参数eventTriggerId标识的位置,在fTriggeredEventClientDatas数组中对应的元素的值改为clientData

之前创建触发器的时候,将fTriggeredEventClientDatas数组的对应位置是置为NULL的。

void BasicTaskScheduler0::triggerEvent(EventTriggerId eventTriggerId, void* clientData) {    // First, record the "clientData":首先,记录“客户端数据”:    if (eventTriggerId == fLastUsedTriggerMask) { // common-case optimization:        fTriggeredEventClientDatas[fLastUsedTriggerNum] = clientData;    }    else {        EventTriggerId mask = 0x80000000;        for (unsigned i = 0; i < MAX_NUM_EVENT_TRIGGERS; ++i) {            if ((eventTriggerId&mask) != 0) {                fTriggeredEventClientDatas[i] = clientData;                fLastUsedTriggerMask = mask;                fLastUsedTriggerNum = i;            }            mask >>= 1;        }    }    // Then, note this event as being ready to be handled.    // (Note that because this function (unlike others in the library) can be called from an external thread, we do this last, to    //  reduce the risk of a race condition.)    //  将fTriggersAwaitingHandling中对应的位置1。    fTriggersAwaitingHandling |= eventTriggerId;}

转载于:https://www.cnblogs.com/oloroso/p/4599973.html

你可能感兴趣的文章
1.汇编指令介绍(arm)
查看>>
在Android中调用C#写的WebService(附源代码)
查看>>
优化 SQL Server CPU 性能
查看>>
一、线性模型
查看>>
动态规划方法总结
查看>>
C语言基础---流程控制-->选择结构
查看>>
php随笔
查看>>
108. Convert Sorted Array to Binary Search Tree
查看>>
数据结构与算法
查看>>
红黑树
查看>>
DIV滚动条
查看>>
YOLOV3 训练WIDER_FACE
查看>>
GIS ftp
查看>>
精品课程-工程测量-第一章-绪论
查看>>
好久没写代码,今天刚刚给客户写了点
查看>>
C++之 类型定义语句--typedef
查看>>
编译器原理(一):类成员函数
查看>>
spring boot 加载配置 文件
查看>>
LeetCode 60. Permutation Sequence
查看>>
dll和so文件区别与构成
查看>>