20_BasicTaskScheduler0 基本任务调度类基类(二)——Live555源码阅读(一

可莉
• 阅读 568

#20_BasicTaskScheduler0 基本任务调度类基类(二)——Live555源码阅读(一)任务调度相关类

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

本文由乌合之众 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;
}
点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
2年前
java目前可以通过以下几种方式进行定时任务
1、单机部署模式Timer:jdk中自带的一个定时调度类,可以简单的实现按某一频度进行任务执行。提供的功能比较单一,无法实现复杂的调度任务。ScheduledExecutorService:也是jdk自带的一个基于线程池设计的定时任务类。其每个调度任务都会分配到线程池中的一个线程执行,所以其任务是并发执行的,互不影响。
待兔 待兔
1星期前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
可莉 可莉
2年前
19_BasicTaskScheduler0 基本任务调度类基类(一)——Live555源码阅读(一
19\_BasicTaskScheduler0基本任务调度类基类(一)——Live555源码阅读(一)任务调度相关类这是Live555源码阅读的第二部分,包括了任务调度相关的三个类。任务调度是Live555源码中很重要的部分。本文由乌
可莉 可莉
2年前
22_BasicTaskScheduler基本任务调度器(二)——Live555源码阅读(一)任务调
22\_BasicTaskScheduler基本任务调度器(二)——Live555源码阅读(一)任务调度相关类\TOC\这是Live555源码阅读的第二部分,包括了任务调度相关的三个类。任务调度是Live555源码中很重要的部分。
可莉 可莉
2年前
21_BasicTaskScheduler基本任务调度器(一)——Live555源码阅读(一)任务调
21\_BasicTaskScheduler基本任务调度器(一)——Live555源码阅读(一)任务调度相关类\TOC\这是Live555源码阅读的第二部分,包括了任务调度相关的三个类。任务调度是Live555源码中很重要的部分。
可莉 可莉
2年前
18 TaskScheduler任务调度器抽象基类——Live555源码阅读(一)任务调度相关类
18TaskScheduler任务调度器抽象基类——Live555源码阅读(一)任务调度相关类这是Live555源码阅读的第二部分,包括了任务调度相关的三个类。任务调度是Live555源码中很重要的部分。本文由乌合之众lym瞎编,欢
可莉 可莉
2年前
17 任务调度相关类综述——Live555源码阅读(一)任务调度相关类
17任务调度相关类综述——Live555源码阅读(一)任务调度相关类这是Live555源码阅读的第二部分,包括了任务调度相关的三个类。任务调度是Live555源码中很重要的部分。本文由乌合之众lym瞎编,欢迎转载my.oschi
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
6个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这