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

本文由乌合之众 lym瞎编,欢迎转载 http://www.cnblogs.com/oloroso/

本文由乌合之众 lym瞎编,欢迎转载 my.oschina.net/oloroso

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;
}

20 BasicTaskScheduler0 基本任务调度类基类(二)——Live555源码阅读(一)任务调度相关类的更多相关文章

  1. 21 BasicTaskScheduler基本任务调度器(一)——Live555源码阅读(一)任务调度相关类

    21_BasicTaskScheduler基本任务调度器(一)——Live555源码阅读(一)任务调度相关类 BasicTaskScheduler基本任务调度器 BasicTaskScheduler基 ...

  2. 19 BasicTaskScheduler0 基本任务调度类基类(一)——Live555源码阅读(一)任务调度相关类

    这是Live555源码阅读的第二部分,包括了任务调度相关的三个类.任务调度是Live555源码中很重要的部分. 本文由乌合之众 lym瞎编,欢迎转载 http://www.cnblogs.com/ol ...

  3. 15 BasicHashTable基本哈希表类(二)——Live555源码阅读(一)基本组件类

    这是Live555源码阅读的第一部分,包括了时间类,延时队列类,处理程序描述类,哈希表类这四个大类. 本文由乌合之众 lym瞎编,欢迎转载 http://www.cnblogs.com/oloroso ...

  4. 3 EventTime 事件时间类和TimeNow函数——Live555源码阅读(一)基本组件类

    这是Live555源码阅读的第一部分,包括了时间类,延时队列类,处理程序描述类,哈希表类这四个大类. 这里是时间相关类的第三个部分,也是最后一个部分. EventTime 事件时间类 这个类和Dela ...

  5. 12 哈希表相关类——Live555源码阅读(一)基本组件类

    12 哈希表相关类--Live555源码阅读(一)基本组件类 这是Live555源码阅读的第一部分,包括了时间类,延时队列类,处理程序描述类,哈希表类这四个大类. 本文由乌合之众 lym瞎编,欢迎转载 ...

  6. 34 网络相关函数(二)——live555源码阅读(四)网络

    34 网络相关函数(二)——live555源码阅读(四)网络 34 网络相关函数(二)——live555源码阅读(四)网络 2)socketErr 套接口错误 3)groupsockPriv函数 4) ...

  7. 18 TaskScheduler任务调度器抽象基类——Live555源码阅读(一)任务调度相关类

    这是Live555源码阅读的第二部分,包括了任务调度相关的三个类.任务调度是Live555源码中很重要的部分. 本文由乌合之众 lym瞎编,欢迎转载 http://www.cnblogs.com/ol ...

  8. 17 任务调度相关类综述——Live555源码阅读(一)任务调度相关类

    这是Live555源码阅读的第二部分,包括了任务调度相关的三个类.任务调度是Live555源码中很重要的部分. 本文由乌合之众 lym瞎编,欢迎转载 http://www.cnblogs.com/ol ...

  9. 11 AlarmHandler定时处理类——Live555源码阅读(一)基本组件类

    这是Live555源码阅读的第一部分,包括了时间类,延时队列类,处理程序描述类,哈希表类这四个大类. 本文由乌合之众 lym瞎编,欢迎转载 http://www.cnblogs.com/oloroso ...

随机推荐

  1. re正则表达式6_+

    + means"match one or more" the group proceding a plus must appear at least once. # -*- cod ...

  2. System类

    System类是一些与系统相关属性和方法的集合,而且System类中所有的属性都是静态的,要想引用这些属性和方法,直接使用System类调用即可. //======================== ...

  3. Ubuntu 设置程序开机启动(以指定用户身份)

    一.方法 在/etc/rc.local写程序的启动命令(系统执行内核过程中会启动init进程,该进程把当前runlevel所对应的的所有service 都启动后,才会执行rc.local里的命令),程 ...

  4. Swift学习二

    // 定义枚举方式一 enum Season { // 每个case定义一个实例 case Spring case Summer case Fall case Winter } // 定义枚举方式二 ...

  5. php Hash Table(一) Hash Table的结构

    关于Hash Table专题: 一直想深入理解一下php的hash table的实现,以前一直是星星点点的看看,从未彻底的总结过,那就从这个专题开始吧! 主要想总结几个部分:hashtable结构,h ...

  6. Bitcask 存储模型

    Bitcask 存储模型 Bitcask 是一个日志型.基于hash表结构的key-value存储模型,以Bitcask为存储模型的K-V系统有 Riak和 beansdb新版本. 日志型数据存储 何 ...

  7. Centos7安装rabbitmq server 3.6.0

    ###假设所有操作在opt目录下进行 cd /opt mkdir apps cd apps ### 下载 RabbitMQ Server wget http://www.rabbitmq.com/re ...

  8. GOF业务场景的设计模式-----观察者模式

    定义:定义对象间一种一对多的依赖关系,使得当每一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新. 在软件系统中经常会有这样的需求:如果一个对象的状态发生改变,某些与它相关的对象也要随之做出 ...

  9. WAMP启动失败简单解决方法

    一般情况下,直接选择安装,突然出现问题了:提示:msvcp110.dll或msvcr110.dll问题, 那么你直接复制这个来百度就行. 在百度会提示让你一键安装并且修复的. 或者你可能会看网上其他教 ...

  10. activiti数据库表结构全貌解析

    http://www.jianshu.com/p/e6971e8a8dad 下面本人介绍一些activiti这款开源流程设计引擎的数据库表结构,首先阐述:我们刚开始接触或者使用一个新的东西(技术)时我 ...