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

可莉
• 阅读 542

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

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

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

##BasicTaskScheduler0 基本任务调度类基类

BasicTaskScheduler0是一个用作传递的类,它继承自TaskScheduler,又派生出BasicTaskScheduler。其定义在live555sourcecontrol\UsageEnvironment\include\BasicUsageEnvironment0.hh文件中。 这个类实现了TaskScheduler中的纯虚接口,并增加了一些数据成员。其中比较重要的两个是fDelayQueue(延时队列)和fHandlers(处理程序集合/链表)。

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

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

##下面是其定义代码,里面有一些是对注释的翻译。

class HandlerSet; // forward

#define MAX_NUM_EVENT_TRIGGERS 32

// An abstract base class, useful for subclassing 抽象基类,用于子类化
// (e.g., to redefine the implementation of socket event handling)
// 例如,重新定义socket事件处理的实现
class BasicTaskScheduler0 : public TaskScheduler {
public:
    //析构的时候 delete fHandlers
    virtual ~BasicTaskScheduler0();

    //设置select轮询的超时时间的最大值,如果maxDelatTime不大于0,那么就设置为一百万秒
    virtual void SingleStep(unsigned maxDelayTime = 0) = 0;
    // "maxDelayTime" is in microseconds.  It allows a subclass to impose a limit
    // maxDelayTime 单位是微秒,它允许一个子类施加限制
    // on how long "select()" can delay, in case it wants to also do polling.
    // 多长时间”select()”可以延迟,如果它想做轮询。
    // 0 (the default value) means: There's no maximum; just look at the delay queue
    // 0作为默认值,意思是:没有最大;只是看看延迟队列

public:
    // Redefined virtual functions:重新定义虚函数

    /* 调度延时任务
    * 1、创建一个AlarmHandler对象(定时处理);(new AlarmHandler(proc, clientData, timeToDelay);)
    * 2、将创建的alarmHandler对象添加到fDelayQueue中;(fDelayQueue.addEntry(alarmHandler))
    * 3、返回这个alarmHandler的token标志
    */
    virtual TaskToken scheduleDelayedTask(int64_t microseconds, TaskFunc* proc,
        void* clientData);

    /* 取消调度延时任务
    * 1、从fDelayeQueue中removeEntry这个prevTask
    * 2、设置prevTask=NULL
    * 3、delete这个prevTask标识的alarmHandler对象
    */
    virtual void unscheduleDelayedTask(TaskToken& prevTask);

    /* 做事件循环
    * 1、判断watchVariable !=0 && *watchVariable != 0是否成立,若成立,函数返回
    * 2、调用函数SingleStep();函数返回后继续做步骤1
    */
    virtual void doEventLoop(char* watchVariable);

    /* 创建事件触发器ID
    *     从fTriggeredEventHandlers数组中寻找一个没有使用的位置 pos。如果没有空位,函数返回0
    *     将eventHandlerProc放置到上述数组 pos 位置
    *     将fTriggeredEventClientDatas数组 pos 位置置为NULL
    *     设置fLastUsedTriggerMask的第 pos 位为1
    *     设置fLastUsedTriggerNum为 pos
    *     返回fLastUsedTriggerMask的值
    */
    virtual EventTriggerId createEventTrigger(TaskFunc* eventHandlerProc);

    /* 删除事件触发器 eventTriggerId可能代表多个事件触发器
    *   设置 fTriggersAwaitingHandling &=~ eventTriggerId 
    *   即将fTriggersAwaitingHandling中对应于eventTriggerId的非零位 置零
    *   从fTriggeredEventHandlers和fTriggeredEventClientDatas中将对应的位置置为NULL
    */
    virtual void deleteEventTrigger(EventTriggerId eventTriggerId);

    /* 触发事件
    *    从fTriggeredEventClientDatas找到eventTriggerId对应的位置,设置为clientData
    *    将fTriggersAwaitingHandling中对应eventTriggerId中的非0位置为1
    */
    virtual void triggerEvent(EventTriggerId eventTriggerId, void* clientData = NULL);

protected:
    BasicTaskScheduler0();

protected:
    // implement vt.实施,执行; 使生效,实现; 落实(政策); 把…填满;n.工具,器械; 家具; 手段;[法]履行(契约等);
    
    // To implement delayed operations: 实施延迟操作:
    DelayQueue fDelayQueue;

    // To implement background reads: 实施后台读
    HandlerSet* fHandlers;        //处理程序描述对象链表指针
    int fLastHandledSocketNum;    //当前最近一个调度的HandlerDescriptor对象的socketNum标识

    // To implement event triggers:    实施时间触发器
    // fTriggersAwaitingHandling触发等待处理的 fLastUsedTriggerMask 最后使用触发器的位置置1
    // implemented as 32-bit bitmaps 实现是32位的比特位图
    EventTriggerId fTriggersAwaitingHandling, fLastUsedTriggerMask;

    TaskFunc* fTriggeredEventHandlers[MAX_NUM_EVENT_TRIGGERS];    //保存事件触发器
    void* fTriggeredEventClientDatas[MAX_NUM_EVENT_TRIGGERS];    //保存触发事件客户端数据
    unsigned fLastUsedTriggerNum; // in the range(范围) [0,MAX_NUM_EVENT_TRIGGERS) 最后使用触发器的
};

##BasicTaskScheduler0的构造与析构 BasicTaskScheduler0的构造内容不多,但是从这里开始要介绍的东西很多。还有注意,这个构造函数是protected权限的。 先来分析一下它的各个数据成员。

int fLastHandledSocketNum; 从字面意思来看,这个成员的意思是保存最后一个处理socket的。但是这只是猜测。这里我们回到前面去看HandlerDescriptor类的定义。其类定义中有一个成员socketNum,用来表示HandlerDescriptor在链表中的唯一存在。是不是这两者就有关联了呢?没错,确实是这样的。这个变量代表的是最后一个被加入的HandlerDescriptor对象

fTriggersAwaitingHandlingfLastUsedTriggerMask这两个一起来说。

这两者的类型是EventTriggerId,实质上是无符号32未整型(u_int32_t)。这两个变量和后面的两个数组对应起来看,这两个数组都是MAX_NUM_EVENT_TRIGGERS个元素的,也就是32。而这里两个变量是32bit,它们的每一个位与数组的一个元素对应是否就刚刚好呢?这里先不说,后面会解释的。(fTriggersAwaitingHandling等待触发集,fLastUsedTriggerMask最近使用的触发器)

fLastUsedTriggerNum这个参数表示的是最后一个使用触发器的位置(在fTriggeredEventHandlers数组中的下标)。它的范围是[0,31]。将其初始化为31,是因为每一次创建触发器的时候会使用这个值。见createEventTriggerd方法。

数组fTriggeredEventHandlers用于保存事件处理程序函数地址,它的每一个元素是一个函数指针。 数组fTriggeredEventClientDatas用于保存事件处理程序函数调用时候的参数,它的元素是void*类型。 DelayQueue fDelayQueue;是一个延时队列,前面介绍过。用于延时处理事件。注意这里这个链表的节点将是AlarmHandler对象。 HandlerSet* fHandlers;这一个用于保存事件处理程序和其客户数据。要注意的是这里是一个指针,而不是对象。在构造的时候创建了一个对象。

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


BasicTaskScheduler0::BasicTaskScheduler0()
  : fLastHandledSocketNum(-1), fTriggersAwaitingHandling(0), fLastUsedTriggerMask(1), fLastUsedTriggerNum(MAX_NUM_EVENT_TRIGGERS-1) {
  fHandlers = new HandlerSet;    //创建对象
  for (unsigned i = 0; i < MAX_NUM_EVENT_TRIGGERS; ++i) {
    fTriggeredEventHandlers[i] = NULL;
    fTriggeredEventClientDatas[i] = NULL;
  }
}

BasicTaskScheduler0的析构就简单很多了。前面说了,只要一个成员fHandlers是指针的,并且在构造的时候动态创建了一个对象给它。所以析构的时候就只是将其delete了。

BasicTaskScheduler0::~BasicTaskScheduler0() {
  delete fHandlers;
}
点赞
收藏
评论区
推荐文章
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自带的一个基于线程池设计的定时任务类。其每个调度任务都会分配到线程池中的一个线程执行,所以其任务是并发执行的,互不影响。
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
可莉 可莉
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年前
20_BasicTaskScheduler0 基本任务调度类基类(二)——Live555源码阅读(一
20\_BasicTaskScheduler0基本任务调度类基类(二)——Live555源码阅读(一)任务调度相关类这是Live555源码阅读的第二部分,包括了任务调度相关的三个类。任务调度是Live555源码中很重要的部分。本文由乌
可莉 可莉
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进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这