PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/dep/acelite/ace/TP_Reactor.cpp

https://github.com/chucho/FaceCore
C++ | 682 lines | 387 code | 134 blank | 161 comment | 74 complexity | bd99e59bf945283b8db728d60d929c34 MD5 | raw file
  1. // $Id: TP_Reactor.cpp 91286 2010-08-05 09:04:31Z johnnyw $
  2. #include "ace/TP_Reactor.h"
  3. #include "ace/Thread.h"
  4. #include "ace/Timer_Queue.h"
  5. #include "ace/Sig_Handler.h"
  6. #include "ace/Log_Msg.h"
  7. #include "ace/OS_NS_sys_time.h"
  8. #if !defined (__ACE_INLINE__)
  9. #include "ace/TP_Reactor.inl"
  10. #endif /* __ACE_INLINE__ */
  11. ACE_BEGIN_VERSIONED_NAMESPACE_DECL
  12. ACE_ALLOC_HOOK_DEFINE (ACE_TP_Reactor)
  13. int
  14. ACE_TP_Token_Guard::acquire_read_token (ACE_Time_Value *max_wait_time)
  15. {
  16. ACE_TRACE ("ACE_TP_Token_Guard::acquire_read_token");
  17. // The order of these events is very subtle, modify with care.
  18. // Try to grab the lock. If someone if already there, don't wake
  19. // them up, just queue up in the thread pool.
  20. int result = 0;
  21. if (max_wait_time)
  22. {
  23. ACE_Time_Value tv = ACE_OS::gettimeofday ();
  24. tv += *max_wait_time;
  25. ACE_MT (result = this->token_.acquire_read (&ACE_TP_Reactor::no_op_sleep_hook,
  26. 0,
  27. &tv));
  28. }
  29. else
  30. {
  31. ACE_MT (result = this->token_.acquire_read (&ACE_TP_Reactor::no_op_sleep_hook));
  32. }
  33. // Check for timeouts and errors.
  34. if (result == -1)
  35. {
  36. if (errno == ETIME)
  37. return 0;
  38. else
  39. return -1;
  40. }
  41. // We got the token and so let us mark ourselves as owner
  42. this->owner_ = true;
  43. return result;
  44. }
  45. int
  46. ACE_TP_Token_Guard::acquire_token (ACE_Time_Value *max_wait_time)
  47. {
  48. ACE_TRACE ("ACE_TP_Token_Guard::acquire_token");
  49. // Try to grab the lock. If someone if already there, don't wake
  50. // them up, just queue up in the thread pool.
  51. int result = 0;
  52. if (max_wait_time)
  53. {
  54. ACE_Time_Value tv = ACE_OS::gettimeofday ();
  55. tv += *max_wait_time;
  56. ACE_MT (result = this->token_.acquire (0,
  57. 0,
  58. &tv));
  59. }
  60. else
  61. {
  62. ACE_MT (result = this->token_.acquire ());
  63. }
  64. // Check for timeouts and errors.
  65. if (result == -1)
  66. {
  67. if (errno == ETIME)
  68. return 0;
  69. else
  70. return -1;
  71. }
  72. // We got the token and so let us mark ourselves as owner
  73. this->owner_ = true;
  74. return result;
  75. }
  76. ACE_TP_Reactor::ACE_TP_Reactor (ACE_Sig_Handler *sh,
  77. ACE_Timer_Queue *tq,
  78. bool mask_signals,
  79. int s_queue)
  80. : ACE_Select_Reactor (sh, tq, ACE_DISABLE_NOTIFY_PIPE_DEFAULT, 0, mask_signals, s_queue)
  81. {
  82. ACE_TRACE ("ACE_TP_Reactor::ACE_TP_Reactor");
  83. this->supress_notify_renew (1);
  84. }
  85. ACE_TP_Reactor::ACE_TP_Reactor (size_t max_number_of_handles,
  86. bool restart,
  87. ACE_Sig_Handler *sh,
  88. ACE_Timer_Queue *tq,
  89. bool mask_signals,
  90. int s_queue)
  91. : ACE_Select_Reactor (max_number_of_handles, restart, sh, tq, ACE_DISABLE_NOTIFY_PIPE_DEFAULT, 0, mask_signals, s_queue)
  92. {
  93. ACE_TRACE ("ACE_TP_Reactor::ACE_TP_Reactor");
  94. this->supress_notify_renew (1);
  95. }
  96. int
  97. ACE_TP_Reactor::owner (ACE_thread_t, ACE_thread_t *o_id)
  98. {
  99. ACE_TRACE ("ACE_TP_Reactor::owner");
  100. if (o_id)
  101. *o_id = ACE_Thread::self ();
  102. return 0;
  103. }
  104. int
  105. ACE_TP_Reactor::owner (ACE_thread_t *t_id)
  106. {
  107. ACE_TRACE ("ACE_TP_Reactor::owner");
  108. *t_id = ACE_Thread::self ();
  109. return 0;
  110. }
  111. int
  112. ACE_TP_Reactor::handle_events (ACE_Time_Value *max_wait_time)
  113. {
  114. ACE_TRACE ("ACE_TP_Reactor::handle_events");
  115. // Stash the current time -- the destructor of this object will
  116. // automatically compute how much time elapsed since this method was
  117. // called.
  118. ACE_Countdown_Time countdown (max_wait_time);
  119. //
  120. // The order of these events is very subtle, modify with care.
  121. //
  122. // Instantiate the token guard which will try grabbing the token for
  123. // this thread.
  124. ACE_TP_Token_Guard guard (this->token_);
  125. int const result = guard.acquire_read_token (max_wait_time);
  126. // If the guard is NOT the owner just return the retval
  127. if (!guard.is_owner ())
  128. return result;
  129. // After getting the lock just just for deactivation..
  130. if (this->deactivated_)
  131. return -1;
  132. // Update the countdown to reflect time waiting for the token.
  133. countdown.update ();
  134. return this->dispatch_i (max_wait_time, guard);
  135. }
  136. int
  137. ACE_TP_Reactor::dispatch_i (ACE_Time_Value *max_wait_time,
  138. ACE_TP_Token_Guard &guard)
  139. {
  140. int event_count = this->get_event_for_dispatching (max_wait_time);
  141. // We use this count to detect potential infinite loops as described
  142. // in bug 2540.
  143. int const initial_event_count = event_count;
  144. int result = 0;
  145. // Note: We are passing the <event_count> around, to have record of
  146. // how many events still need processing. May be this could be
  147. // useful in future.
  148. #if 0
  149. // @Ciju
  150. // signal handling isn't in a production state yet.
  151. // Commenting it out for now.
  152. // Dispatch signals
  153. if (event_count == -1)
  154. {
  155. // Looks like we dont do any upcalls in dispatch signals. If at
  156. // a later point of time, we decide to handle signals we have to
  157. // release the lock before we make any upcalls.. What is here
  158. // now is not the right thing...
  159. //
  160. // @@ We need to do better..
  161. return this->handle_signals (event_count, guard);
  162. }
  163. #endif // #if 0
  164. // If there are no signals and if we had received a proper
  165. // event_count then first look at dispatching timeouts. We need to
  166. // handle timers early since they may have higher latency
  167. // constraints than I/O handlers. Ideally, the order of dispatching
  168. // should be a strategy...
  169. // NOTE: The event count does not have the number of timers that
  170. // needs dispatching. But we are still passing this along. We dont
  171. // need to do that. In the future we *may* have the timers also
  172. // returned through the <event_count>. Just passing that along for
  173. // that day.
  174. result = this->handle_timer_events (event_count, guard);
  175. if (result > 0)
  176. return result;
  177. // Else just go ahead fall through for further handling.
  178. if (event_count > 0)
  179. {
  180. // Next dispatch the notification handlers (if there are any to
  181. // dispatch). These are required to handle multiple-threads
  182. // that are trying to update the <Reactor>.
  183. result = this->handle_notify_events (event_count, guard);
  184. if (result > 0)
  185. return result;
  186. // Else just fall through for further handling
  187. }
  188. if (event_count > 0)
  189. {
  190. // Handle socket events
  191. result = this->handle_socket_events (event_count, guard);
  192. }
  193. if (event_count != 0 && event_count == initial_event_count)
  194. {
  195. this->state_changed_ = true;
  196. }
  197. return result;
  198. }
  199. #if 0
  200. // @Ciju
  201. // signal handling isn't in a production state yet.
  202. // Commenting it out for now.
  203. int
  204. ACE_TP_Reactor::handle_signals (int & /*event_count*/,
  205. ACE_TP_Token_Guard & /*guard*/)
  206. {
  207. ACE_TRACE ("ACE_TP_Reactor::handle_signals");
  208. /*
  209. *
  210. * THIS METHOD SEEMS BROKEN
  211. *
  212. *
  213. */
  214. // First check for interrupts.
  215. // Bail out -- we got here since <select> was interrupted.
  216. if (ACE_Sig_Handler::sig_pending () != 0)
  217. {
  218. ACE_Sig_Handler::sig_pending (0);
  219. // This piece of code comes from the old TP_Reactor. We did not
  220. // handle signals at all then. If we happen to handle signals
  221. // in the TP_Reactor, we should then start worryiung about this
  222. // - Bala 21-Aug- 01
  223. if 0
  224. // Not sure if this should be done in the TP_Reactor
  225. // case... leave it out for now. -Steve Huston 22-Aug-00
  226. // If any HANDLES in the <ready_set_> are activated as a
  227. // result of signals they should be dispatched since
  228. // they may be time critical...
  229. active_handle_count = this->any_ready (dispatch_set);
  230. else
  231. // active_handle_count = 0;
  232. endif
  233. // Record the fact that the Reactor has dispatched a
  234. // handle_signal() method. We need this to return the
  235. // appropriate count.
  236. return 1;
  237. }
  238. return -1;
  239. }
  240. #endif // #if 0
  241. int
  242. ACE_TP_Reactor::handle_timer_events (int & /*event_count*/,
  243. ACE_TP_Token_Guard &guard)
  244. {
  245. if (this->timer_queue_ == 0 || this->timer_queue_->is_empty())
  246. { // Empty timer queue so cannot have any expired timers.
  247. return 0;
  248. }
  249. // Get the current time
  250. ACE_Time_Value cur_time (this->timer_queue_->gettimeofday () +
  251. this->timer_queue_->timer_skew ());
  252. // Look for a node in the timer queue whose timer <= the present
  253. // time.
  254. ACE_Timer_Node_Dispatch_Info info;
  255. if (this->timer_queue_->dispatch_info (cur_time, info))
  256. {
  257. const void *upcall_act = 0;
  258. // Preinvoke.
  259. this->timer_queue_->preinvoke (info, cur_time, upcall_act);
  260. // Release the token before dispatching notifies...
  261. guard.release_token ();
  262. // call the functor
  263. this->timer_queue_->upcall (info, cur_time);
  264. // Postinvoke
  265. this->timer_queue_->postinvoke (info, cur_time, upcall_act);
  266. // We have dispatched a timer
  267. return 1;
  268. }
  269. return 0;
  270. }
  271. int
  272. ACE_TP_Reactor::handle_notify_events (int & /*event_count*/,
  273. ACE_TP_Token_Guard &guard)
  274. {
  275. // Get the handle on which notify calls could have occured
  276. ACE_HANDLE notify_handle = this->get_notify_handle ();
  277. int result = 0;
  278. // The notify was not in the list returned by
  279. // wait_for_multiple_events ().
  280. if (notify_handle == ACE_INVALID_HANDLE)
  281. return result;
  282. // Now just do a read on the pipe..
  283. ACE_Notification_Buffer buffer;
  284. // Clear the handle of the read_mask of our <ready_set_>
  285. this->ready_set_.rd_mask_.clr_bit (notify_handle);
  286. // Keep reading notifies till we empty it or till we have a
  287. // dispatchable buffer
  288. while (this->notify_handler_->read_notify_pipe (notify_handle, buffer) > 0)
  289. {
  290. // Just figure out whether we can read any buffer that has
  291. // dispatchable info. If not we have just been unblocked by
  292. // another thread trying to update the reactor. If we get any
  293. // buffer that needs dispatching we will dispatch that after
  294. // releasing the lock
  295. if (this->notify_handler_->is_dispatchable (buffer) > 0)
  296. {
  297. // Release the token before dispatching notifies...
  298. guard.release_token ();
  299. // Dispatch the upcall for the notify
  300. this->notify_handler_->dispatch_notify (buffer);
  301. // We had a successful dispatch.
  302. result = 1;
  303. // break out of the while loop
  304. break;
  305. }
  306. }
  307. // If we did some work, then we just return 1 which will allow us
  308. // to get out of here. If we return 0, then we will be asked to do
  309. // some work ie. dispacth socket events
  310. return result;
  311. }
  312. int
  313. ACE_TP_Reactor::handle_socket_events (int &event_count,
  314. ACE_TP_Token_Guard &guard)
  315. {
  316. // We got the lock, lets handle some I/O events.
  317. ACE_EH_Dispatch_Info dispatch_info;
  318. this->get_socket_event_info (dispatch_info);
  319. // If there is any event handler that is ready to be dispatched, the
  320. // dispatch information is recorded in dispatch_info.
  321. if (!dispatch_info.dispatch ())
  322. {
  323. // Check for removed handlers.
  324. if (dispatch_info.event_handler_ == 0)
  325. {
  326. this->handler_rep_.unbind(dispatch_info.handle_,
  327. dispatch_info.mask_);
  328. }
  329. return 0;
  330. }
  331. // Suspend the handler so that other threads don't start dispatching
  332. // it, if we can't suspend then return directly
  333. //
  334. // NOTE: This check was performed in older versions of the
  335. // TP_Reactor. Looks like it is a waste..
  336. if (dispatch_info.event_handler_ != this->notify_handler_)
  337. if (this->suspend_i (dispatch_info.handle_) == -1)
  338. return 0;
  339. // Call add_reference() if needed.
  340. if (dispatch_info.reference_counting_required_)
  341. dispatch_info.event_handler_->add_reference ();
  342. // Release the lock. Others threads can start waiting.
  343. guard.release_token ();
  344. int result = 0;
  345. // If there was an event handler ready, dispatch it.
  346. // Decrement the event left
  347. --event_count;
  348. // Dispatched an event
  349. if (this->dispatch_socket_event (dispatch_info) == 0)
  350. ++result;
  351. return result;
  352. }
  353. int
  354. ACE_TP_Reactor::get_event_for_dispatching (ACE_Time_Value *max_wait_time)
  355. {
  356. // If the reactor handler state has changed, clear any remembered
  357. // ready bits and re-scan from the master wait_set.
  358. if (this->state_changed_)
  359. {
  360. this->ready_set_.rd_mask_.reset ();
  361. this->ready_set_.wr_mask_.reset ();
  362. this->ready_set_.ex_mask_.reset ();
  363. this->state_changed_ = false;
  364. }
  365. else
  366. {
  367. // This is a hack... somewhere, under certain conditions (which
  368. // I don't understand...) the mask will have all of its bits clear,
  369. // yet have a size_ > 0. This is an attempt to remedy the affect,
  370. // without knowing why it happens.
  371. this->ready_set_.rd_mask_.sync (this->ready_set_.rd_mask_.max_set ());
  372. this->ready_set_.wr_mask_.sync (this->ready_set_.wr_mask_.max_set ());
  373. this->ready_set_.ex_mask_.sync (this->ready_set_.ex_mask_.max_set ());
  374. }
  375. return this->wait_for_multiple_events (this->ready_set_, max_wait_time);
  376. }
  377. int
  378. ACE_TP_Reactor::get_socket_event_info (ACE_EH_Dispatch_Info &event)
  379. {
  380. // Check for dispatch in write, except, read. Only catch one, but if
  381. // one is caught, be sure to clear the handle from each mask in case
  382. // there is more than one mask set for it. This would cause problems
  383. // if the handler is suspended for dispatching, but its set bit in
  384. // another part of ready_set_ kept it from being dispatched.
  385. int found_io = 0;
  386. ACE_HANDLE handle;
  387. // @@todo: We can do quite a bit of code reduction here. Let me get
  388. // it to work before I do this.
  389. {
  390. ACE_Handle_Set_Iterator handle_iter (this->ready_set_.wr_mask_);
  391. while (!found_io && (handle = handle_iter ()) != ACE_INVALID_HANDLE)
  392. {
  393. if (this->is_suspended_i (handle))
  394. continue;
  395. // Remember this info
  396. event.set (handle,
  397. this->handler_rep_.find (handle),
  398. ACE_Event_Handler::WRITE_MASK,
  399. &ACE_Event_Handler::handle_output);
  400. this->clear_handle_read_set (handle);
  401. found_io = 1;
  402. }
  403. }
  404. if (!found_io)
  405. {
  406. ACE_Handle_Set_Iterator handle_iter (this->ready_set_.ex_mask_);
  407. while (!found_io && (handle = handle_iter ()) != ACE_INVALID_HANDLE)
  408. {
  409. if (this->is_suspended_i (handle))
  410. continue;
  411. // Remember this info
  412. event.set (handle,
  413. this->handler_rep_.find (handle),
  414. ACE_Event_Handler::EXCEPT_MASK,
  415. &ACE_Event_Handler::handle_exception);
  416. this->clear_handle_read_set (handle);
  417. found_io = 1;
  418. }
  419. }
  420. if (!found_io)
  421. {
  422. ACE_Handle_Set_Iterator handle_iter (this->ready_set_.rd_mask_);
  423. while (!found_io && (handle = handle_iter ()) != ACE_INVALID_HANDLE)
  424. {
  425. if (this->is_suspended_i (handle))
  426. continue;
  427. // Remember this info
  428. event.set (handle,
  429. this->handler_rep_.find (handle),
  430. ACE_Event_Handler::READ_MASK,
  431. &ACE_Event_Handler::handle_input);
  432. this->clear_handle_read_set (handle);
  433. found_io = 1;
  434. }
  435. }
  436. return found_io;
  437. }
  438. // Dispatches a single event handler
  439. int
  440. ACE_TP_Reactor::dispatch_socket_event (ACE_EH_Dispatch_Info &dispatch_info)
  441. {
  442. ACE_TRACE ("ACE_TP_Reactor::dispatch_socket_event");
  443. ACE_Event_Handler * const event_handler = dispatch_info.event_handler_;
  444. ACE_EH_PTMF const callback = dispatch_info.callback_;
  445. // Check for removed handlers.
  446. if (event_handler == 0)
  447. return -1;
  448. // Upcall. If the handler returns positive value (requesting a
  449. // reactor callback) don't set the ready-bit because it will be
  450. // ignored if the reactor state has changed. Just call back
  451. // as many times as the handler requests it. Other threads are off
  452. // handling other things.
  453. int status = 1;
  454. while (status > 0)
  455. status = (event_handler->*callback) (dispatch_info.handle_);
  456. // Post process socket event
  457. return this->post_process_socket_event (dispatch_info, status);
  458. }
  459. int
  460. ACE_TP_Reactor::post_process_socket_event (ACE_EH_Dispatch_Info &dispatch_info,
  461. int status)
  462. {
  463. int result = 0;
  464. // First check if we really have to post process something, if not, then
  465. // we don't acquire the token which saves us a lot of time.
  466. if (status < 0 ||
  467. (dispatch_info.event_handler_ != this->notify_handler_ &&
  468. dispatch_info.resume_flag_ ==
  469. ACE_Event_Handler::ACE_REACTOR_RESUMES_HANDLER))
  470. {
  471. // Get the reactor token and with this token acquired remove first the
  472. // handler and resume it at the same time. This must be atomic, see also
  473. // bugzilla 2395. When this is not atomic it can be that we resume the
  474. // handle after it is reused by the OS.
  475. ACE_TP_Token_Guard guard (this->token_);
  476. result = guard.acquire_token ();
  477. // If the guard is NOT the owner just return the retval
  478. if (!guard.is_owner ())
  479. return result;
  480. // A different event handler may have been registered during the
  481. // upcall if the handle was closed and then reopened, for
  482. // example. Make sure we're removing and/or resuming the event
  483. // handler used during the upcall.
  484. ACE_Event_Handler const * const eh =
  485. this->handler_rep_.find (dispatch_info.handle_);
  486. // Only remove or resume the event handler used during the
  487. // upcall.
  488. if (eh == dispatch_info.event_handler_)
  489. {
  490. if (status < 0)
  491. {
  492. result =
  493. this->remove_handler_i (dispatch_info.handle_,
  494. dispatch_info.mask_);
  495. }
  496. // Resume handler if required.
  497. if (dispatch_info.event_handler_ != this->notify_handler_ &&
  498. dispatch_info.resume_flag_ ==
  499. ACE_Event_Handler::ACE_REACTOR_RESUMES_HANDLER)
  500. this->resume_i (dispatch_info.handle_);
  501. }
  502. }
  503. // Call remove_reference() if needed.
  504. if (dispatch_info.reference_counting_required_)
  505. dispatch_info.event_handler_->remove_reference ();
  506. return result;
  507. }
  508. int
  509. ACE_TP_Reactor::resumable_handler (void)
  510. {
  511. return 1;
  512. }
  513. int
  514. ACE_TP_Reactor::handle_events (ACE_Time_Value &max_wait_time)
  515. {
  516. return this->handle_events (&max_wait_time);
  517. }
  518. void
  519. ACE_TP_Reactor::notify_handle (ACE_HANDLE,
  520. ACE_Reactor_Mask,
  521. ACE_Handle_Set &,
  522. ACE_Event_Handler *eh,
  523. ACE_EH_PTMF)
  524. {
  525. ACE_ERROR ((LM_ERROR,
  526. ACE_TEXT ("ACE_TP_Reactor::notify_handle: ")
  527. ACE_TEXT ("Wrong version of notify_handle() got called\n")));
  528. ACE_ASSERT (eh == 0);
  529. ACE_UNUSED_ARG (eh);
  530. }
  531. ACE_HANDLE
  532. ACE_TP_Reactor::get_notify_handle (void)
  533. {
  534. // Call the notify handler to get a handle on which we would have a
  535. // notify waiting
  536. ACE_HANDLE const read_handle =
  537. this->notify_handler_->notify_handle ();
  538. // Check whether the rd_mask has been set on that handle. If so
  539. // return the handle.
  540. if (read_handle != ACE_INVALID_HANDLE &&
  541. this->ready_set_.rd_mask_.is_set (read_handle))
  542. {
  543. return read_handle;
  544. }
  545. // None found..
  546. return ACE_INVALID_HANDLE;
  547. }
  548. ACE_END_VERSIONED_NAMESPACE_DECL