【转载请注明出处】:http://blog.csdn.net/longlong530

学习TaskThread主要有三个类要关注:

TaskTreadPool: 任务线程池

TaskThread:任务线程

Task: 任务

1. TaskThreadPool
Darwin运行着一个或者多个任务(Task)线程,并将他们统一在线程池TaskThreadPool中管理。任务线程从事件线程中接收RTSP和RTP请求,然后把请求传递到恰当的服务器模块进行处理,把数据包发送给客户端。
缺省情况下,核心服务器为每一个处理器创建一个任务线程。(numProcessors = OS::GetNumProcessors();)

  1.  
    TaskThreadPool::SetNumShortTaskThreads(numShortTaskThreads);
  2.  
    TaskThreadPool::SetNumBlockingTaskThreads(numBlockingThreads);
  3.  
    TaskThreadPool::AddThreads(numThreads);
  4.  
    sServer->InitNumThreads(numThreads);

2. TaskThread

所有的Task对象都将在TaskThread中运行,TaskThread通过运行Task类型对象的Run方法来完成相应Task的处理。TaskThread的个数是可配置的,缺省情况下TaskThread的个数与处理器的个数一致。等待被TaskThread调用并运行的Task放在队列或者堆中。

  1.  
    void TaskThread::Entry()
  2.  
    {
  3.  
    Task* theTask = NULL;
  4.  
     
  5.  
    while (true)
  6.  
    {
  7.  
    //不停的从内部的队列中取到Task才返回;,此时的Task既不在堆中,也不在队列中;
  8.  
    theTask = this->WaitForTask();
  9.  
    /*此处省略,主要是对调用task的Run方法的返回值做不同的分支处理,详细分析在Task章节介绍*/
  10.  
    }
  11.  
     

我们还是仔细分析下WaitForTask方法吧:

  1.  
    Task* TaskThread::WaitForTask()
  2.  
    {
  3.  
    while (true)
  4.  
    {
  5.  
    SInt64 theCurrentTime = OS::Milliseconds();
  6.  
    /*如果堆中有任务,且任务已经到执行时间,返回该任务。
  7.  
    PeekMin函数见OSHeap.h,窃听堆中第一个元素(但不取出)*/
  8.  
    if ((fHeap.PeekMin() != NULL) && (fHeap.PeekMin()->GetValue() <= theCurrentTime))
  9.  
    {
  10.  
    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());
  11.  
    return (Task*)fHeap.ExtractMin()->GetEnclosingObject();//从堆中取出第一个任务返回
  12.  
    }
  13.  
    //如果堆中有任务,但是尚未到执行时间,计算需要等待的时间
  14.  
    //if there is an element waiting for a timeout, figure out how long we should wait.
  15.  
    SInt64 theTimeout = 0;
  16.  
    if (fHeap.PeekMin() != NULL)
  17.  
    theTimeout = fHeap.PeekMin()->GetValue() - theCurrentTime;
  18.  
    Assert(theTimeout >= 0);
  19.  
     
  20.  
    //
  21.  
    // Make sure we can't go to sleep for some ridiculously short
  22.  
    // period of time
  23.  
    // Do not allow a timeout below 10 ms without first verifying reliable udp 1-2mbit live streams.
  24.  
    // Test with streamingserver.xml pref reliablUDP printfs enabled and look for packet loss and check client for buffer ahead recovery.
  25.  
    if (theTimeout < 10)
  26.  
    theTimeout = 10;
  27.  
     
  28.  
    //wait...
  29.  
    //如果任务队列为空,就等待theTimeout时间后从堆中取出任务返回;
  30.  
    //如果任务队列不为空,就不等待,直接取队列中的任务;
  31.  
    OSQueueElem* theElem = fTaskQueue.DeQueueBlocking(this, (SInt32) theTimeout);
  32.  
    if (theElem != NULL)
  33.  
    {
  34.  
    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() );
  35.  
    return (Task*)theElem->GetEnclosingObject();
  36.  
    }
  37.  
     
  38.  
    //
  39.  
    // If we are supposed to stop, return NULL, which signals the caller to stop
  40.  
    if (OSThread::GetCurrent()->IsStopRequested())
  41.  
    return NULL;
  42.  
    }
  43.  
    }

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的更多相关文章

  1. 【Darwin学习笔记】之获取系统处理器数量的方法

    阅读Darwin源码的时候看到这个方法,感觉挺有用处,且考虑了多种平台下的实现方式,直接贴代码,以后说不定会用到~ 单一种平台下的实现方法可能很容易,但是把这些个系统都收集在一起,在一个函数中实现还是 ...

  2. golang学习笔记5 用bee工具创建项目 bee工具简介

    golang学习笔记5 用bee工具创建项目 bee工具简介 Bee 工具的使用 - beego: 简约 & 强大并存的 Go 应用框架https://beego.me/docs/instal ...

  3. go 学习笔记之值得特别关注的基础语法有哪些

    在上篇文章中,我们动手亲自编写了第一个 Go 语言版本的 Hello World,并且认识了 Go 语言中有意思的变量和不安分的常量. 相信通过上篇文章的斐波那契数列,你已经初步掌握了 Go 语言的变 ...

  4. Quartz学习笔记:基础知识

    Quartz学习笔记:基础知识 引入Quartz 关于任务调度 关于任务调度,Java.util.Timer是最简单的一种实现任务调度的方法,简单的使用如下: import java.util.Tim ...

  5. 学习笔记:CentOS7学习之十六:LVM管理和ssm存储管理器使用

    目录 学习笔记:CentOS7学习之十六:LVM管理和ssm存储管理器使用 16.1 LVM的工作原理 16.1.1 LVM常用术语 16.1.2 LVM优点 16.2 创建LVM的基本步骤 16.2 ...

  6. Node.JS学习——学习笔记

    Node.JS--学习笔记 2020年02月23日11:52:01 我打算自学NodeJS-通过阅读NodeJS官网来完成. https://nodejs.org/dist/latest-v13.x/ ...

  7. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  8. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  9. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

随机推荐

  1. select标签(分组下拉菜单和列表)

    分组下拉菜单和列表标签: <select name=" " > <optgroup label="组1"> <option val ...

  2. Gym.101955: Asia Shenyang Regional Contest(寒假自训第10场)

    C.Insertion Sort 题意:Q次询问,每次给出N,M,Mod,问你有多少种排列,满足前面M个数字排序之后整个序列的LIS>=N-1. 思路:我们把数字看成[1,M],[N-M+1,N ...

  3. 网页筛选Automatic Input Enrichment - FLAIR

    http://www.cs.rochester.edu/~tetreaul/Presentations-and-Posters/0504.pdf 介绍了一个在线平台https://eflnotes.w ...

  4. es6的let与es5的var定义变量的区别

    es6的let与es5的var定义变量的区别 自身新手第一次接触let关键字的时候,不知道let与var的区别,本能认为是一样,但非如此,比如下述的代码运行就会报错: let hello = 'hel ...

  5. Windows 10下使用WMware 12 安装Ubuntu16.04,安装过程(附全过程图)

    序言:菜鸡的我又开始瞎搞Ubuntu了 首先在网下下载VMware 12 正常安装即可 关于产品密匙问题:5A02H-AU243-TZJ49-GTC7K-3C61N (这是我在网上找的密匙,反正自己是 ...

  6. PS学习之小猪佩奇身上纹,掌声送给社会人

    首先准备素材 用ps首先打开素材一 首先对图片去色 快捷键:shift+Ctrl+u 调整色阶 设置高斯模糊: 另存为psd格式,命名为叠加的对象 再次打开素材一,把佩奇拖入到图层里,并调整大小,旋转 ...

  7. scikit-learn数据集下载太慢的问题

    有时候用scikit-learn在线下载数据时太慢,因为网络或者其他原因,这时候我们可以先把数据集下载到本地,然后再把这个数据集放到scikit-learn的data中,首先我们需要找到 scikit ...

  8. windows下能搭建php-fpm吗 phpstudy

    这个Windows和Linux系统是不一样的,因为一般nginx搭配php需要php-fpm中间件,但是Windows下需要第三方编译. 下载的包里有php-cgi.exe 但不是php-fpm如果想 ...

  9. php 数组排序 按照某字段

    $arr=[     array(         'name'=>'小坏龙',         'age'=>28     ),     array(         'name'=&g ...

  10. js 数字数组按大小排序

    var num = [7,8,6,5,2] //倒序排列 num.sort((a,b)=>{return b-a}) //正序排列 num.sort((a,b)=>{return a-b} ...