三、消息循环

 三  消息循环 
看服端的主体:live555MediaServer.cpp 中的 main()函数,可见其创建一个 RTSPServer
类实例后,即进入一个函数 env->taskScheduler().doEventLoop()中,看名字很明显是一个
消息循坏,执行到里面后不停地转圈,生名不息,转圈不止。那么在这个人生的圈圈中如何
实现 RTSP 服务和 RTP 传输呢?别想那么远了,还是先看这个圈圈中实现了什么功能吧。 
[cpp]   
1. void BasicTaskScheduler0::doEventLoop(char* watchVariable) {   
2.     // Repeatedly loop, handling readble sockets and timed events:     
3.     while (1) {   
4.         if (watchVariable != NULL && *watchVariable != 0)   
5.             break;   
6.         SingleStep();   
7.     }   
8. }   
BasicTaskScheduler0 从 TaskScheduler 派生,所以还是一个任务调度对象,所以依然说
明任务调度对象是整个程序的发动机。   
循环中每次走一步:SingleStep()。这走一步中都做些什么呢? 总结为以下四步: 
1为所有需要操作的 socket 执行 select。 
2找出第一个应执行的 socket 任务(handler)并执行之。 
3找到第一个应响应的事件,并执行之。 
4找到第一个应执行的延迟任务并执行之。 
可见,每一步中只执行三个任务队列中的一项。下面详细分析函数 SingleStep(): 
[cpp] view plaincopyprint? 
1. //循坏中主要执行的函数     
2. void BasicTaskScheduler::SingleStep(unsigned maxDelayTime) {   
3.     fd_set readSet = fReadSet; // make a copy for this select() call     
4.     fd_set writeSet = fWriteSet; // ditto     
5.     fd_set exceptionSet = fExceptionSet; // ditto     
6.    
7.     //计算 select socket 们时的超时时间。     
8.     DelayInterval const& timeToDelay = fDelayQueue.timeToNextAlarm();   
9.     struct timeval tv_timeToDelay;   
10.     tv_timeToDelay.tv_sec = timeToDelay.seconds();   
11.     tv_timeToDelay.tv_usec = timeToDelay.useconds();   
12.     // Very large "tv_sec" values cause select() to fail.     
13.     // Don't make it any larger than 1 million seconds (11.5 days)     
14.     const long MAX_TV_SEC = MILLION;   
15.     if (tv_timeToDelay.tv_sec > MAX_TV_SEC) {   
16.         tv_timeToDelay.tv_sec = MAX_TV_SEC;   
17.     }   
18.     // Also check our "maxDelayTime" parameter (if it's > 0):     
19.     if (maxDelayTime > 0   
20.             && (tv_timeToDelay.tv_sec > (long) maxDelayTime / MILLION   
21.                     || (tv_timeToDelay.tv_sec == (long) maxDelayTime / MILLION   
22.                             && tv_timeToDelay.tv_usec   
23.                                     > (long) maxDelayTime % MILLION))) {   24.         tv_timeToDelay.tv_sec = maxDelayTime / MILLION;   
25.         tv_timeToDelay.tv_usec = maxDelayTime % MILLION;   
26.     }   
27.    
28.     //先执行 socket 的 select 操作,以确定哪些 socket 任务(handler)需要执行。     
29.     int selectResult = select(fMaxNumSockets,   
30.             &readSet, &writeSet,&exceptionSet,   
31.             &tv_timeToDelay);   
32.    
33.     if (selectResult < 0) {   
34. //#if defined(__WIN32__) || defined(_WIN32)     
35.         int err = WSAGetLastError();   
36.         // For some unknown reason, select() in Windoze sometimes fails with W
SAEINVAL if     
37.         // it was called with no entries set in "readSet".  If this happens, ignore it: 
   
38.         if (err == WSAEINVAL && readSet.fd_count == 0) {   
39.             err = EINTR;   
40.             // To stop this from happening again, create a dummy socket:     
41.             int dummySocketNum = socket(AF_INET, SOCK_DGRAM, 0);   
42.             FD_SET((unsigned) dummySocketNum, &fReadSet);   
43.         }   
44.         if (err != EINTR) {   
45. //#else     
46. //      if (errno != EINTR && errno != EAGAIN) {     
47. //#endif     
48.             // Unexpected error - treat this as fatal:     
49. //#if !defined(_WIN32_WCE)     
50. //          perror("BasicTaskScheduler::SingleStep(): select() fails");     
51. //#endif     
52.             internalError();   
53.         }   
54.     }   
55.    
56.     // Call the handler function for one readable socket:     57.     HandlerIterator iter(*fHandlers);   
58.     HandlerDescriptor* handler;   
59.     // To ensure forward progress through the handlers, begin past the last     
60.     // socket number that we handled:     
61.     if (fLastHandledSocketNum >= 0) {   
62.         //找到上次执行的 socket handler 的下一个     
63.         while ((handler = iter.next()) != NULL) {   
64.             if (handler->socketNum == fLastHandledSocketNum)   
65.                 break;   
66.         }   
67.         if (handler == NULL) {   
68.             fLastHandledSocketNum = -1;   
69.             iter.reset(); // start from the beginning instead     
70.         }   
71.     }   
72.    
73.     //从找到的 handler 开始,找一个可以执行的 handler,不论其状态是可读,可
写,还是出错,执行之。     
74.     while ((handler = iter.next()) != NULL) {   
75.         int sock = handler->socketNum; // alias     
76.         int resultConditionSet = 0;   
77.         if (FD_ISSET(sock, &readSet)   
78.                 && FD_ISSET(sock, &fReadSet)/*sanity check*/)   
79.             resultConditionSet |= SOCKET_READABLE;   
80.         if (FD_ISSET(sock, &writeSet)   
81.                 && FD_ISSET(sock, &fWriteSet)/*sanity check*/)   
82.             resultConditionSet |= SOCKET_WRITABLE;   
83.         if (FD_ISSET(sock, &exceptionSet)   
84.                 && FD_ISSET(sock, &fExceptionSet)/*sanity check*/)   
85.             resultConditionSet |= SOCKET_EXCEPTION;   
86.         if ((resultConditionSet & handler->conditionSet)   
87.                 != 0 && handler->handlerProc != NULL) {   
88.             fLastHandledSocketNum = sock;   
89.             // Note: we set "fLastHandledSocketNum" before calling the handler,     
90.             // in case the handler calls "doEventLoop()" reentrantly.     91.             (*handler->handlerProc)(handler->clientData, resultConditionSet);   
92.             break;   
93.         }   
94.     }   
95.    
96.     //如果寻找完了依然没有执行任何 handle,则从头再找。     
97.     if (handler == NULL && fLastHandledSocketNum >= 0) {   
98.         // We didn't call a handler, but we didn't get to check all of them,     
99.         // so try again from the beginning:     
100.          iter.reset();   
101.          while ((handler = iter.next()) != NULL) {   
102.              int sock = handler->socketNum; // alias     
103.              int resultConditionSet = 0;   
104.              if (FD_ISSET(sock, &readSet)&& FD_ISSET(sock, &fReadSet)/*san
ity check*/)   
105.                  resultConditionSet |= SOCKET_READABLE;   
106.              if (FD_ISSET(sock, &writeSet)&& FD_ISSET(sock, &fWriteSet)/*san
ity check*/)   
107.                  resultConditionSet |= SOCKET_WRITABLE;   
108.              if (FD_ISSET(sock, &exceptionSet)   && FD_ISSET(sock, &fExcepti
onSet)/*sanity check*/)   
109.                  resultConditionSet |= SOCKET_EXCEPTION;   
110.              if ((resultConditionSet & handler->conditionSet)   
111.                      != 0 && handler->handlerProc != NULL) {   
112.                  fLastHandledSocketNum = sock;   
113.                  // Note: we set "fLastHandledSocketNum" before calling the handl
er,     
114.                  // in case the handler calls "doEventLoop()" reentrantly.     
115.                  (*handler->handlerProc)(handler->clientData, resultConditionSet); 
116.                  break;   
117.              }   
118.          }   
119.          //依然没有找到可执行的 handler。     
120.          if (handler == NULL)   
121.              fLastHandledSocketNum = -1; //because we didn't call a handler     122.      }   
123.      //响应事件     
124.      // Also handle any newly-triggered event     
125.      // (Note that we do this *after* calling a socket handler,     
126.      // in case the triggered event handler modifies The set of readable socket
s.)     
127.      if (fTriggersAwaitingHandling != 0) {   
128.          if (fTriggersAwaitingHandling == fLastUsedTriggerMask) {   
129.              // Common-case optimization for a single event trigger:     
130.              fTriggersAwaitingHandling = 0;   
131.              if (fTriggeredEventHandlers[fLastUsedTriggerNum] != NULL) {   
132.                  //执行一个事件处理函数     
133.                  (*fTriggeredEventHandlers[fLastUsedTriggerNum])(fTriggeredEv
entClientDatas[fLastUsedTriggerNum]);   
134.              }   
135.          } else {   
136.              // Look for an event trigger that needs handling     
137.              // (making sure that we make forward progress through all possible t
riggers):     
138.              unsigned i = fLastUsedTriggerNum;   
139.              EventTriggerId mask = fLastUsedTriggerMask;   
140.              do {   
141.                  i = (i + 1) % MAX_NUM_EVENT_TRIGGERS;   
142.                  mask >>= 1;   
143.                  if (mask == 0)   
144.                      mask = 0x80000000;   
145.                  if ((fTriggersAwaitingHandling & mask) != 0) {   
146.                      //执行一个事件响应     
147.                      fTriggersAwaitingHandling &= ~mask;   
148.                      if (fTriggeredEventHandlers[i] != NULL) {   
149.                          (*fTriggeredEventHandlers[i])(fTriggeredEventClientDatas[i])
;   
150.                      }   
151.                      fLastUsedTriggerMask = mask;   
152.                      fLastUsedTriggerNum = i;   153.                      break;   
154.                  }   
155.              } while (i != fLastUsedTriggerNum);   
156.          }   
157.      }   
158.      //执行一个最迫切的延迟任务。     
159.      // Also handle any delayed event that may have come due.     
160.      fDelayQueue.handleAlarm();   
161.  }   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值