文档章节

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

乌合之众
 乌合之众
发布于 2015/06/16 08:56
字数 1562
阅读 28
收藏 0

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

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

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

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

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

BasicTaskScheduler0

BasicTaskScheduler0

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

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;这一个用于保存事件处理程序和其客户数据。要注意的是这里是一个指针,而不是对象。在构造的时候创建了一个对象。

BasicTaskScheduler0


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

© 著作权归作者所有

乌合之众
粉丝 14
博文 90
码字总数 79438
作品 1
海淀
程序员
私信 提问
Live555学习基础类

Live555主要用到的类介绍: 1.UsageEnvironment类:抽象基类 class UsageEnvironment {public:void reclaim(); TaskScheduler& taskScheduler() const {return fScheduler;}//返回TaskSched......

rootusers
2015/01/08
0
0
RTSP学习笔记(1)live555

1、UsageEnvironment UsageEnvironment代表了整个程序的运行环境,其中保存了一些全局变量,定义了一些输出函数(纯虚函数)。从这些输出函数就可以看出该类主要用于充当程序的全局上下文,并...

Sean-x
2016/02/23
95
0
Live555源代码解读(3)

四、计划任务(TaskScheduler) 我们且把三种任务命名为:socket handler,event handler,delay task。这三种任务的特点是,前两个加入执行队列后会一直存在,而delay task在执行完一次后会立...

Sean-x
2016/02/24
48
0
taobao-pamirs-schedule-2.0源码分析——类设计

使用方法 首先学习一个开源项目,一定要先学习该开源项目的使用方法。该项目的使用方法本文不再详述。请参考博文: http://pinsir.iteye.com/blog/882275 http://pinsir.iteye.com/blog/882...

杨武兵
2016/03/02
1K
8
Live555源代码解读(1)

一、整体架构 从程序的结构来看,live项目包括了四个基本库、程序入口类(在mediaServer中)和一些测试代码(在testProgs中)。四个基本库是UsageEnvironment、BasicUsageEnvironment、group...

Sean-x
2016/02/24
325
0

没有更多内容

加载失败,请刷新页面

加载更多

golang-字符串-地址分析

demo package mainimport "fmt"func main() {str := "map.baidu.com"fmt.Println(&str, str)str = str[0:5]fmt.Println(&str, str)str = "abc"fmt.Println(&s......

李琼涛
今天
4
0
Spring Boot WebFlux 增删改查完整实战 demo

03:WebFlux Web CRUD 实践 前言 上一篇基于功能性端点去创建一个简单服务,实现了 Hello 。这一篇用 Spring Boot WebFlux 的注解控制层技术创建一个 CRUD WebFlux 应用,让开发更方便。这里...

泥瓦匠BYSocket
今天
6
0
从0开始学FreeRTOS-(列表与列表项)-3

FreeRTOS列表&列表项的源码解读 第一次看列表与列表项的时候,感觉很像是链表,虽然我自己的链表也不太会,但是就是感觉很像。 在FreeRTOS中,列表与列表项使用得非常多,是FreeRTOS的一个数...

杰杰1号
今天
8
0
Java反射

Java 反射 反射是框架设计的灵魂(使用的前提条件:必须先得到代表的字节码的 Class,Class 类 用于表示.class 文件(字节码)) 一、反射的概述 定义:JAVA 反射机制是在运行状态中,对于任...

zzz1122334
今天
6
0
聊聊nacos的LocalConfigInfoProcessor

序 本文主要研究一下nacos的LocalConfigInfoProcessor LocalConfigInfoProcessor nacos-1.1.3/client/src/main/java/com/alibaba/nacos/client/config/impl/LocalConfigInfoProcessor.java p......

go4it
昨天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部