文档章节

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

乌合之众
 乌合之众
发布于 2015/06/16 08:58
字数 1093
阅读 72
收藏 0

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

© 著作权归作者所有

乌合之众
粉丝 13
博文 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
53
0
Live555源代码解读(3)

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

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

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

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

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

Sean-x
2016/02/24
251
0

没有更多内容

加载失败,请刷新页面

加载更多

硬件配置

https://akkadia.org/drepper/futex.pdf sudo lshw -businfo[sudo] lambda 的密码: Bus info Device Class Description======================================......

MtrS
今天
2
0
springmvc的return “success”源码解读

qqqq

architect刘源源
今天
4
0
Java程序员五面阿里分享 逆袭成功 太不容易了!

前言 拿到阿里实习offer,经历了5次面试,其中4轮技术面,1轮HR面试。在这里分享一下自己的面试经验和学习心得。希望能够帮助更多的小伙伴。 我本科毕业于中南大学信管专业,真正开始学习Jav...

别打我会飞
昨天
4
0
Android Camera模块解析之视频录制

《Android Camera架构》 《Android Camera进程间通信类总结》 《Android Camera模块解析之拍照》 《Android Camera模块解析之视频录制》 《Android Camera原理之CameraDeviceCallbacks回调模...

天王盖地虎626
昨天
2
0
手把手教你使用issue作为博客评论系统

自从上周在阮一峰的 每周分享第 60 期 看到了可以将 GitHub 的 issue 当作评论系统,插入第三方网页的 JS 库——utterances。我就对此“魂牵梦绕”。个人博客使用的是VuePress。 TLDR (不多废...

jump--jump
昨天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部