【Darwin学习笔记】之TaskThread
【转载请注明出处】:http://blog.csdn.net/longlong530
学习TaskThread主要有三个类要关注:
TaskTreadPool: 任务线程池
TaskThread:任务线程
Task: 任务
1. TaskThreadPool
Darwin运行着一个或者多个任务(Task)线程,并将他们统一在线程池TaskThreadPool中管理。任务线程从事件线程中接收RTSP和RTP请求,然后把请求传递到恰当的服务器模块进行处理,把数据包发送给客户端。
缺省情况下,核心服务器为每一个处理器创建一个任务线程。(numProcessors = OS::GetNumProcessors();)
- TaskThreadPool::SetNumShortTaskThreads(numShortTaskThreads);
- TaskThreadPool::SetNumBlockingTaskThreads(numBlockingThreads);
- TaskThreadPool::AddThreads(numThreads);
- sServer->InitNumThreads(numThreads);
2. TaskThread
所有的Task对象都将在TaskThread中运行,TaskThread通过运行Task类型对象的Run方法来完成相应Task的处理。TaskThread的个数是可配置的,缺省情况下TaskThread的个数与处理器的个数一致。等待被TaskThread调用并运行的Task放在队列或者堆中。
- void TaskThread::Entry()
- {
- Task* theTask = NULL;
- while (true)
- {
- //不停的从内部的队列中取到Task才返回;,此时的Task既不在堆中,也不在队列中;
- theTask = this->WaitForTask();
- /*此处省略,主要是对调用task的Run方法的返回值做不同的分支处理,详细分析在Task章节介绍*/
- }
我们还是仔细分析下WaitForTask方法吧:
- Task* TaskThread::WaitForTask()
- {
- while (true)
- {
- SInt64 theCurrentTime = OS::Milliseconds();
- /*如果堆中有任务,且任务已经到执行时间,返回该任务。
- PeekMin函数见OSHeap.h,窃听堆中第一个元素(但不取出)*/
- if ((fHeap.PeekMin() != NULL) && (fHeap.PeekMin()->GetValue() <= theCurrentTime))
- {
- if (TASK_DEBUG) qtss_printf("TaskThread::WaitForTask found timer-task=%s thread %p fHeap.CurrentHeapSize(%"_U32BITARG_") taskElem = %p enclose=%p\n",((Task*)fHeap.PeekMin()->GetEnclosingObject())->fTaskName, (void *) this, fHeap.CurrentHeapSize(), (void *) fHeap.PeekMin(), (void *) fHeap.PeekMin()->GetEnclosingObject());
- return (Task*)fHeap.ExtractMin()->GetEnclosingObject();//从堆中取出第一个任务返回
- }
- //如果堆中有任务,但是尚未到执行时间,计算需要等待的时间
- //if there is an element waiting for a timeout, figure out how long we should wait.
- SInt64 theTimeout = 0;
- if (fHeap.PeekMin() != NULL)
- theTimeout = fHeap.PeekMin()->GetValue() - theCurrentTime;
- Assert(theTimeout >= 0);
- //
- // Make sure we can't go to sleep for some ridiculously short
- // period of time
- // Do not allow a timeout below 10 ms without first verifying reliable udp 1-2mbit live streams.
- // Test with streamingserver.xml pref reliablUDP printfs enabled and look for packet loss and check client for buffer ahead recovery.
- if (theTimeout < 10)
- theTimeout = 10;
- //wait...
- //如果任务队列为空,就等待theTimeout时间后从堆中取出任务返回;
- //如果任务队列不为空,就不等待,直接取队列中的任务;
- OSQueueElem* theElem = fTaskQueue.DeQueueBlocking(this, (SInt32) theTimeout);
- if (theElem != NULL)
- {
- if (TASK_DEBUG) qtss_printf("TaskThread::WaitForTask found signal-task=%s thread %p fTaskQueue.GetLength(%"_U32BITARG_") taskElem = %p enclose=%p\n", ((Task*)theElem->GetEnclosingObject())->fTaskName, (void *) this, fTaskQueue.GetQueue()->GetLength(), (void *) theElem, (void *)theElem->GetEnclosingObject() );
- return (Task*)theElem->GetEnclosingObject();
- }
- //
- // If we are supposed to stop, return NULL, which signals the caller to stop
- if (OSThread::GetCurrent()->IsStopRequested())
- return NULL;
- }
- }
3. Task
每个Task对象有两个主要的方法:Signal和Run。
3.1 Run()
Run()方法是在Task对象获得处理该事件的时间片后运行的,Darwin中的大部分工作都是在不同Task对象的Run()函数中进行的。
比如常见的Task类型是RTSPSession和RTPSession。
在这里程序的返回值是一个重要的信息:
当返回-1时,表明任务已经完全结束,程序会直接删除该Task指针;
当返回0时,线程接着执行下一个Task,表明任务希望在下次传信时被再次立即执行;
当返回一个正数n时,线程会在 n毫秒后再次调用这个Task的Run函数。将该任务加入到Heap中,并且纪录它希望等待的时间。Entry()函数将通过waitfortask()函数进行检测,如果等待的时间到了,就再次运行该任务
(注意; 在我们继承Task类,而重写Run虚函数时,我们第一件要作的事情是运行Task类的GetEvent()函数。)
virtual SInt64 Run() = 0;
3.2 Signal()
当服务器希望发送一个事件给某个Task对象时,就会调用Signal()方法;
将该任务加入到指定任务线程的任务队列中,如果不存在指定的任务线程,就在线程池中随机选择一个任务线程运行该任务
void Signal(EventFlags eventFlags);
【Darwin学习笔记】之TaskThread的更多相关文章
- 【Darwin学习笔记】之获取系统处理器数量的方法
阅读Darwin源码的时候看到这个方法,感觉挺有用处,且考虑了多种平台下的实现方式,直接贴代码,以后说不定会用到~ 单一种平台下的实现方法可能很容易,但是把这些个系统都收集在一起,在一个函数中实现还是 ...
- golang学习笔记5 用bee工具创建项目 bee工具简介
golang学习笔记5 用bee工具创建项目 bee工具简介 Bee 工具的使用 - beego: 简约 & 强大并存的 Go 应用框架https://beego.me/docs/instal ...
- go 学习笔记之值得特别关注的基础语法有哪些
在上篇文章中,我们动手亲自编写了第一个 Go 语言版本的 Hello World,并且认识了 Go 语言中有意思的变量和不安分的常量. 相信通过上篇文章的斐波那契数列,你已经初步掌握了 Go 语言的变 ...
- Quartz学习笔记:基础知识
Quartz学习笔记:基础知识 引入Quartz 关于任务调度 关于任务调度,Java.util.Timer是最简单的一种实现任务调度的方法,简单的使用如下: import java.util.Tim ...
- 学习笔记:CentOS7学习之十六:LVM管理和ssm存储管理器使用
目录 学习笔记:CentOS7学习之十六:LVM管理和ssm存储管理器使用 16.1 LVM的工作原理 16.1.1 LVM常用术语 16.1.2 LVM优点 16.2 创建LVM的基本步骤 16.2 ...
- Node.JS学习——学习笔记
Node.JS--学习笔记 2020年02月23日11:52:01 我打算自学NodeJS-通过阅读NodeJS官网来完成. https://nodejs.org/dist/latest-v13.x/ ...
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
- PHP-自定义模板-学习笔记
1. 开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2. 整体架构图 ...
- PHP-会员登录与注册例子解析-学习笔记
1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...
随机推荐
- 牛客国庆集训派对Day1 L-New Game!(最短路)
链接:https://www.nowcoder.com/acm/contest/201/L 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 1048576K,其他语言20 ...
- ZOJ 1005:Jugs(思维)
Jugs Time Limit: 2 Seconds Memory Limit: 65536 KB Special Judge In the movie "Die Har ...
- Mybatis(七)-- LRU LFU 算法
这篇博客主要介绍LRU LFU 算法,因为在Mybatis的缓存中会用到,所以放到这个系列中了.此外,这是我翻译的一篇文章,觉得原文已经写的很好了,所以就直接翻译一下,留作知识整理. 英文原文出处如下 ...
- 下面有关 JAVA 异常类的描述,说法正确的有()
都是Throwable的子类: 1.Exception(异常) :是程序本身可以处理的异常. 2.Error(错误): 是程序无法处理的错误.这些错误表示故障发生于虚拟机自身.或者发生在虚拟机试图执行 ...
- redux笔记1
1.安装redux 使用 npm install -save redux 安装redux,注意使用-save 表示安装到依赖中: 2. 创建store文件夹,下面创建 index.js 和 re ...
- zabbix使用企业微信发送告警信息
用qq邮箱发送告警信息一点都不方便,看到网上说也可以使用微信发送告警信息,所以就试了一下. 首先先试着在虚拟主机上给微信发送信息. 我们需要注册企业微信,注册时有一个地方需要注意,就是注册时选择组织, ...
- win7启动老是自动进入Boot Menu无法进入系统
如图 进入bios设置 点击startup 选择UEFI/Legacy Boot 那里的Legacy Only选项,选择另一个就会出现这种问题 正常进入系统
- JSON数据的优化
JSON数据的可以优化吗?肯定可以,之前都是使用XML,但之后用XML越来越少了,就是因为XML包含的冗余信息太多了.那么JSON数据有没有冗余呢? 肯定有,名称就是重复的!! 例如如下的JSON数据 ...
- .Net培训班课程体系
.Net培训 第一部分:.Net基础 .Net基础:数据类型.变量.运算符.分支结构.循环结构.方法.反编译器.递归.递归算法的非递归优化: 面向对象:异常.封装继承多态.单例模式.装饰者设计模式.t ...
- 手动部署etcd-2018-0731
手动部署很简单,这里花了10分钟搞定 部署etcd 3台机器 etcd:由于 raft 算法的特性,集群的节点数必须是奇数 [root@linux-node1 ~]# cat /etc/hosts 1 ...