【Darwin学习笔记】之TaskThread

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

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

TaskTreadPool: 任务线程池

TaskThread:任务线程

Task: 任务


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

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  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放在队列或者堆中。

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  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.      }  

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

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  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()函数。)
[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. virtual SInt64 Run() = 0;  

       

3.2 Signal()

当服务器希望发送一个事件给某个Task对象时,就会调用Signal()方法;
将该任务加入到指定任务线程的任务队列中,如果不存在指定的任务线程,就在线程池中随机选择一个任务线程运行该任务
[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. void  Signal(EventFlags eventFlags);  

【转载请注明出处】:http://blog.youkuaiyun.com/longlong530
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sunxiaopengsun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值