Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / Select_Reactor_T.cpp
blobd9f02176e6c91a3b277fb0df3a46a0098adff625
1 #ifndef ACE_SELECT_REACTOR_T_CPP
2 #define ACE_SELECT_REACTOR_T_CPP
4 #include "ace/Select_Reactor_T.h"
6 #if !defined (ACE_LACKS_PRAGMA_ONCE)
7 # pragma once
8 #endif /* ACE_LACKS_PRAGMA_ONCE */
10 #include "ace/ACE.h"
11 #include "ace/Guard_T.h"
12 #include "ace/Log_Category.h"
13 #include "ace/Signal.h"
14 #include "ace/Sig_Handler.h"
15 #include "ace/Thread.h"
16 #include "ace/Timer_Heap.h"
17 #include "ace/OS_NS_errno.h"
18 #include "ace/OS_NS_sys_select.h"
19 #include "ace/OS_NS_sys_stat.h"
21 // For timer_queue_
22 #include "ace/Recursive_Thread_Mutex.h"
24 #if !defined (__ACE_INLINE__)
25 #include "ace/Select_Reactor_T.inl"
26 #endif /* __ACE_INLINE__ */
28 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
30 ACE_ALLOC_HOOK_DEFINE_Tc(ACE_Select_Reactor_T)
32 template <class ACE_SELECT_REACTOR_TOKEN> int
33 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::any_ready
34 (ACE_Select_Reactor_Handle_Set &wait_set)
36 ACE_TRACE ("ACE_Select_Reactor_T::any_ready");
38 if (this->mask_signals_)
40 #if !defined (ACE_WIN32)
41 // Make this call signal safe.
42 ACE_Sig_Guard sb;
43 #endif /* ACE_WIN32 */
45 return this->any_ready_i (wait_set);
47 return this->any_ready_i (wait_set);
50 template <class ACE_SELECT_REACTOR_TOKEN> int
51 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::any_ready_i
52 (ACE_Select_Reactor_Handle_Set &wait_set)
54 ACE_TRACE ("ACE_Select_Reactor_T::any_ready_i");
56 int const number_ready = this->ready_set_.rd_mask_.num_set ()
57 + this->ready_set_.wr_mask_.num_set ()
58 + this->ready_set_.ex_mask_.num_set ();
60 // number_ready > 0 meaning there are handles in the ready_set
61 // &wait_set != &(this->ready_set_) means that we need to copy
62 // the handles from the ready_set to the wait set because the
63 // wait_set_ doesn't contain all the handles in the ready_set_
64 if (number_ready > 0 && &wait_set != &(this->ready_set_))
66 wait_set.rd_mask_ = this->ready_set_.rd_mask_;
67 wait_set.wr_mask_ = this->ready_set_.wr_mask_;
68 wait_set.ex_mask_ = this->ready_set_.ex_mask_;
70 this->ready_set_.rd_mask_.reset ();
71 this->ready_set_.wr_mask_.reset ();
72 this->ready_set_.ex_mask_.reset ();
75 return number_ready;
78 template <class ACE_SELECT_REACTOR_TOKEN> int
79 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::handler_i (int signum,
80 ACE_Event_Handler **eh)
82 ACE_TRACE ("ACE_Select_Reactor_T::handler_i");
83 ACE_Event_Handler *handler = this->signal_handler_->handler (signum);
85 if (handler == 0)
86 return -1;
87 else if (eh != 0)
88 *eh = handler;
89 return 0;
92 template <class ACE_SELECT_REACTOR_TOKEN> bool
93 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::initialized ()
95 ACE_TRACE ("ACE_Select_Reactor_T::initialized");
96 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, false));
97 return this->initialized_;
101 template <class ACE_SELECT_REACTOR_TOKEN> int
102 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::owner (ACE_thread_t tid,
103 ACE_thread_t *o_id)
105 ACE_TRACE ("ACE_Select_Reactor_T::owner");
106 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
108 if (o_id)
110 *o_id = this->owner_;
113 this->owner_ = tid;
115 return 0;
118 template <class ACE_SELECT_REACTOR_TOKEN> int
119 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::owner (ACE_thread_t *t_id)
121 ACE_TRACE ("ACE_Select_Reactor_T::owner");
122 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
123 *t_id = this->owner_;
124 return 0;
127 template <class ACE_SELECT_REACTOR_TOKEN> bool
128 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::restart ()
130 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, false));
131 return this->restart_;
134 template <class ACE_SELECT_REACTOR_TOKEN> bool
135 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::restart (bool r)
137 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, false));
138 bool const current_value = this->restart_;
139 this->restart_ = r;
140 return current_value;
143 template <class ACE_SELECT_REACTOR_TOKEN> void
144 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::requeue_position (int rp)
146 ACE_TRACE ("ACE_Select_Reactor_T::requeue_position");
147 ACE_MT (ACE_GUARD (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_));
148 #if defined (ACE_WIN32)
149 ACE_UNUSED_ARG (rp);
150 // Must always requeue ourselves "next" on Win32.
151 this->requeue_position_ = 0;
152 #else
153 this->requeue_position_ = rp;
154 #endif /* ACE_WIN32 */
157 template <class ACE_SELECT_REACTOR_TOKEN> int
158 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::requeue_position ()
160 ACE_TRACE ("ACE_Select_Reactor_T::requeue_position");
161 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
162 return this->requeue_position_;
165 template <class ACE_SELECT_REACTOR_TOKEN> void
166 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::max_notify_iterations (int iterations)
168 ACE_TRACE ("ACE_Select_Reactor_T::max_notify_iterations");
169 ACE_MT (ACE_GUARD (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_));
171 this->notify_handler_->max_notify_iterations (iterations);
174 template <class ACE_SELECT_REACTOR_TOKEN> int
175 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::max_notify_iterations ()
177 ACE_TRACE ("ACE_Select_Reactor_T::max_notify_iterations");
178 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
179 return this->notify_handler_->max_notify_iterations ();
182 // Enqueue ourselves into the list of waiting threads.
183 template <class ACE_SELECT_REACTOR_TOKEN> void
184 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::renew ()
186 ACE_TRACE ("ACE_Select_Reactor_T::renew");
187 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
188 if (!this->supress_notify_renew ())
189 this->token_.renew (this->requeue_position_);
190 #endif /* defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) */
193 template <class ACE_SELECT_REACTOR_TOKEN> int
194 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::notify (ACE_Event_Handler *eh,
195 ACE_Reactor_Mask mask,
196 ACE_Time_Value *timeout)
198 ACE_TRACE ("ACE_Select_Reactor_T::notify");
200 // Pass over both the Event_Handler *and* the mask to allow the
201 // caller to dictate which Event_Handler method the receiver
202 // invokes. Note that this call can timeout.
203 ssize_t n = -1;
204 if (this->notify_handler_)
206 n = this->notify_handler_->notify (eh, mask, timeout);
208 return n == -1 ? -1 : 0;
211 template <class ACE_SELECT_REACTOR_TOKEN> int
212 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::resume_handler (ACE_HANDLE handle)
214 ACE_TRACE ("ACE_Select_Reactor_T::resume_handler");
215 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
216 return this->resume_i (handle);
219 template <class ACE_SELECT_REACTOR_TOKEN> int
220 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::suspend_handler (ACE_HANDLE handle)
222 ACE_TRACE ("ACE_Select_Reactor_T::suspend_handler");
223 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
224 return this->suspend_i (handle);
227 template <class ACE_SELECT_REACTOR_TOKEN> int
228 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::suspend_handlers ()
230 ACE_TRACE ("ACE_Select_Reactor_T::suspend_handlers");
231 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
233 ACE_Event_Handler *eh = 0;
235 for (ACE_Select_Reactor_Handler_Repository_Iterator iter (&this->handler_rep_);
236 iter.next (eh) != 0;
237 iter.advance ())
239 this->suspend_i (eh->get_handle ());
242 return 0;
245 template <class ACE_SELECT_REACTOR_TOKEN> int
246 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::resume_handlers ()
248 ACE_TRACE ("ACE_Select_Reactor_T::resume_handlers");
249 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
251 ACE_Event_Handler *eh = 0;
253 for (ACE_Select_Reactor_Handler_Repository_Iterator iter (&this->handler_rep_);
254 iter.next (eh) != 0;
255 iter.advance ())
257 this->resume_i (eh->get_handle ());
260 return 0;
263 template <class ACE_SELECT_REACTOR_TOKEN> int
264 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::register_handler
265 (ACE_Event_Handler *handler,
266 ACE_Reactor_Mask mask)
268 ACE_TRACE ("ACE_Select_Reactor_T::register_handler");
269 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
270 return this->register_handler_i (handler->get_handle (), handler, mask);
273 template <class ACE_SELECT_REACTOR_TOKEN> int
274 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::register_handler
275 (ACE_HANDLE handle,
276 ACE_Event_Handler *handler,
277 ACE_Reactor_Mask mask)
279 ACE_TRACE ("ACE_Select_Reactor_T::register_handler");
280 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
281 return this->register_handler_i (handle, handler, mask);
284 template <class ACE_SELECT_REACTOR_TOKEN> int
285 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::register_handler
286 (const ACE_Handle_Set &handles,
287 ACE_Event_Handler *handler,
288 ACE_Reactor_Mask mask)
290 ACE_TRACE ("ACE_Select_Reactor_T::register_handler");
291 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
292 return this->register_handler_i (handles, handler, mask);
295 template <class ACE_SELECT_REACTOR_TOKEN> ACE_Event_Handler *
296 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::find_handler
297 (ACE_HANDLE handle)
299 ACE_TRACE ("ACE_Select_Reactor_T::find_handler");
300 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, 0));
301 return this->find_handler_i (handle);
304 template <class ACE_SELECT_REACTOR_TOKEN> int
305 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::handler
306 (ACE_HANDLE handle,
307 ACE_Reactor_Mask mask,
308 ACE_Event_Handler **handler)
310 ACE_TRACE ("ACE_Select_Reactor_T::handler");
311 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
312 return this->handler_i (handle, mask, handler);
315 template <class ACE_SELECT_REACTOR_TOKEN> int
316 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::remove_handler
317 (const ACE_Handle_Set &handles,
318 ACE_Reactor_Mask mask)
320 ACE_TRACE ("ACE_Select_Reactor_T::remove_handler");
321 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
322 return this->remove_handler_i (handles, mask);
325 template <class ACE_SELECT_REACTOR_TOKEN> int
326 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::remove_handler
327 (ACE_Event_Handler *handler,
328 ACE_Reactor_Mask mask)
330 ACE_TRACE ("ACE_Select_Reactor_T::remove_handler");
331 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
332 return this->remove_handler_i (handler->get_handle (), mask);
335 template <class ACE_SELECT_REACTOR_TOKEN> int
336 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::remove_handler
337 (ACE_HANDLE handle,
338 ACE_Reactor_Mask mask)
340 ACE_TRACE ("ACE_Select_Reactor_T::remove_handler");
341 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
342 return this->remove_handler_i (handle, mask);
345 // Performs operations on the "ready" bits.
347 template <class ACE_SELECT_REACTOR_TOKEN> int
348 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::ready_ops
349 (ACE_HANDLE handle,
350 ACE_Reactor_Mask mask,
351 int ops)
353 ACE_TRACE ("ACE_Select_Reactor_T::ready_ops");
354 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
355 return this->bit_ops (handle,
356 mask,
357 this->ready_set_,
358 ops);
361 template <class ACE_SELECT_REACTOR_TOKEN> int
362 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::open
363 (size_t size,
364 bool restart,
365 ACE_Sig_Handler *sh,
366 ACE_Timer_Queue *tq,
367 int disable_notify_pipe,
368 ACE_Reactor_Notify *notify)
370 ACE_TRACE ("ACE_Select_Reactor_T::open");
371 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
373 // Can't initialize ourselves more than once.
374 if (this->initialized_)
375 return -1;
377 this->owner_ = ACE_Thread::self ();
378 this->restart_ = restart;
379 this->signal_handler_ = sh;
380 this->timer_queue_ = tq;
381 this->notify_handler_ = notify;
383 int result = 0;
385 // Allows the signal handler to be overridden.
386 if (this->signal_handler_ == 0)
388 ACE_NEW_RETURN (this->signal_handler_,
389 ACE_Sig_Handler,
390 -1);
392 this->delete_signal_handler_ = true;
395 // Allows the timer queue to be overridden.
396 if (result != -1 && this->timer_queue_ == 0)
398 ACE_NEW_RETURN (this->timer_queue_,
399 ACE_Timer_Heap,
400 -1);
402 this->delete_timer_queue_ = true;
405 // Allows the Notify_Handler to be overridden.
406 if (result != -1 && this->notify_handler_ == 0)
408 ACE_NEW_RETURN (this->notify_handler_,
409 ACE_Select_Reactor_Notify,
410 -1);
412 this->delete_notify_handler_ = true;
415 if (result != -1 && this->handler_rep_.open (size) == -1)
416 result = -1;
417 else if (this->notify_handler_->open (this,
419 disable_notify_pipe) == -1)
421 ACELIB_ERROR ((LM_ERROR,
422 ACE_TEXT ("%p\n"),
423 ACE_TEXT ("ACE_Select_Reactor_T::open, ")
424 ACE_TEXT ("notification pipe open failed")));
425 result = -1;
428 if (result != -1)
429 // We're all set to go.
430 this->initialized_ = true;
431 else
432 // This will close down all the allocated resources properly.
433 this->close ();
435 return result;
438 template <class ACE_SELECT_REACTOR_TOKEN> int
439 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::set_sig_handler
440 (ACE_Sig_Handler *signal_handler)
442 delete this->signal_handler_;
443 this->signal_handler_ = signal_handler;
444 this->delete_signal_handler_ = false;
445 return 0;
448 template <class ACE_SELECT_REACTOR_TOKEN> ACE_Timer_Queue *
449 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::timer_queue () const
451 return this->timer_queue_;
454 template <class ACE_SELECT_REACTOR_TOKEN> int
455 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::timer_queue
456 (ACE_Timer_Queue *tq)
458 if (this->delete_timer_queue_)
460 delete this->timer_queue_;
462 else if (this->timer_queue_)
464 this->timer_queue_->close ();
466 this->timer_queue_ = tq;
467 this->delete_timer_queue_ = false;
468 return 0;
471 template <class ACE_SELECT_REACTOR_TOKEN>
472 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::ACE_Select_Reactor_T
473 (ACE_Sig_Handler *sh,
474 ACE_Timer_Queue *tq,
475 int disable_notify_pipe,
476 ACE_Reactor_Notify *notify,
477 bool mask_signals,
478 int s_queue)
479 : ACE_Select_Reactor_Impl (mask_signals)
480 , token_ (s_queue)
481 , lock_adapter_ (token_)
482 , deactivated_ (0)
484 ACE_TRACE ("ACE_Select_Reactor_T::ACE_Select_Reactor_T");
486 this->token_.reactor (*this);
487 // First try to open the Reactor with the hard-coded default.
488 if (this->open (ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::DEFAULT_SIZE,
492 disable_notify_pipe,
493 notify) == -1)
495 // The hard-coded default Reactor size failed, so attempt to
496 // determine the size at run-time by checking the process file
497 // descriptor limit on platforms that support this feature.
499 // reset the errno so that subsequent checks are valid
500 errno = 0;
502 // There is no need to deallocate resources from previous open()
503 // call since the open() method deallocates any resources prior
504 // to exiting if an error was encountered.
506 // Set the default reactor size to be the current limit on the
507 // number of file descriptors available to the process. This
508 // size is not necessarily the maximum limit.
509 if (this->open (ACE::max_handles (),
513 disable_notify_pipe,
514 notify) == -1)
515 ACELIB_ERROR ((LM_ERROR,
516 ACE_TEXT ("%p\n"),
517 ACE_TEXT ("ACE_Select_Reactor_T::open ")
518 ACE_TEXT ("failed inside ")
519 ACE_TEXT ("ACE_Select_Reactor_T::CTOR")));
523 // Initialize ACE_Select_Reactor_T.
525 template <class ACE_SELECT_REACTOR_TOKEN>
526 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::ACE_Select_Reactor_T
527 (size_t size,
528 bool restart,
529 ACE_Sig_Handler *sh,
530 ACE_Timer_Queue *tq,
531 int disable_notify_pipe,
532 ACE_Reactor_Notify *notify,
533 bool mask_signals,
534 int s_queue)
535 : ACE_Select_Reactor_Impl (mask_signals)
536 , token_ (s_queue)
537 , lock_adapter_ (token_)
538 , deactivated_ (0)
540 ACE_TRACE ("ACE_Select_Reactor_T::ACE_Select_Reactor_T");
542 this->token_.reactor (*this);
543 if (this->open (size,
544 restart,
547 disable_notify_pipe,
548 notify) == -1)
549 ACELIB_ERROR ((LM_ERROR,
550 ACE_TEXT ("%p\n"),
551 ACE_TEXT ("ACE_Select_Reactor_T::open ")
552 ACE_TEXT ("failed inside ACE_Select_Reactor_T::CTOR")));
555 // Close down the ACE_Select_Reactor_T instance, detaching any
556 // remaining Event_Handers. This had better be called from the main
557 // event loop thread...
559 template <class ACE_SELECT_REACTOR_TOKEN> int
560 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::close ()
562 ACE_TRACE ("ACE_Select_Reactor_T::close");
563 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
565 if (this->delete_signal_handler_)
567 delete this->signal_handler_;
568 this->signal_handler_ = 0;
569 this->delete_signal_handler_ = false;
572 this->handler_rep_.close ();
574 if (this->delete_timer_queue_)
576 delete this->timer_queue_;
577 this->timer_queue_ = 0;
578 this->delete_timer_queue_ = false;
580 else if (this->timer_queue_)
582 this->timer_queue_->close ();
583 this->timer_queue_ = 0;
586 if (this->notify_handler_ != 0)
587 this->notify_handler_->close ();
589 if (this->delete_notify_handler_)
591 delete this->notify_handler_;
592 this->notify_handler_ = 0;
593 this->delete_notify_handler_ = false;
596 this->initialized_ = false;
598 return 0;
601 template <class ACE_SELECT_REACTOR_TOKEN> int
602 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::current_info
603 (ACE_HANDLE, size_t &)
605 return -1;
608 template <class ACE_SELECT_REACTOR_TOKEN>
609 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::~ACE_Select_Reactor_T ()
611 ACE_TRACE ("ACE_Select_Reactor_T::~ACE_Select_Reactor_T");
612 this->close ();
615 template <class ACE_SELECT_REACTOR_TOKEN> int
616 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::remove_handler_i
617 (const ACE_Handle_Set &handles,
618 ACE_Reactor_Mask mask)
620 ACE_TRACE ("ACE_Select_Reactor_T::remove_handler_i");
621 ACE_HANDLE h;
623 ACE_Handle_Set_Iterator handle_iter (handles);
625 while ((h = handle_iter ()) != ACE_INVALID_HANDLE)
626 if (this->remove_handler_i (h, mask) == -1)
627 return -1;
629 return 0;
632 template <class ACE_SELECT_REACTOR_TOKEN> int
633 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::register_handler_i
634 (const ACE_Handle_Set &handles,
635 ACE_Event_Handler *handler,
636 ACE_Reactor_Mask mask)
638 ACE_TRACE ("ACE_Select_Reactor_T::register_handler_i");
639 ACE_HANDLE h;
641 ACE_Handle_Set_Iterator handle_iter (handles);
642 while ((h = handle_iter ()) != ACE_INVALID_HANDLE)
643 if (this->register_handler_i (h, handler, mask) == -1)
644 return -1;
646 return 0;
649 template <class ACE_SELECT_REACTOR_TOKEN> int
650 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::register_handler
651 (const ACE_Sig_Set &sigset,
652 ACE_Event_Handler *new_sh,
653 ACE_Sig_Action *new_disp)
655 ACE_TRACE ("ACE_Select_Reactor_T::register_handler");
657 int result = 0;
659 #if (ACE_NSIG > 0)
660 for (int s = 1; s < ACE_NSIG; ++s)
661 if ((sigset.is_member (s) == 1)
662 && this->signal_handler_->register_handler (s,
663 new_sh,
664 new_disp) == -1)
665 result = -1;
666 #else /* ACE_NSIG <= 0 */
667 ACE_UNUSED_ARG (sigset);
668 ACE_UNUSED_ARG (new_sh);
669 ACE_UNUSED_ARG (new_disp);
670 #endif /* ACE_NSIG <= 0 */
671 return result;
674 template <class ACE_SELECT_REACTOR_TOKEN> int
675 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::remove_handler
676 (const ACE_Sig_Set &sigset)
678 ACE_TRACE ("ACE_Select_Reactor_T::remove_handler");
679 int result = 0;
681 #if (ACE_NSIG > 0)
682 for (int s = 1; s < ACE_NSIG; ++s)
683 if ((sigset.is_member (s) == 1)
684 && this->signal_handler_->remove_handler (s) == -1)
685 result = -1;
686 #else /* ACE_NSIG <= 0 */
687 ACE_UNUSED_ARG (sigset);
688 #endif /* ACE_NSIG <= 0 */
690 return result;
693 template <class ACE_SELECT_REACTOR_TOKEN> int
694 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::cancel_timer (ACE_Event_Handler *handler,
695 int dont_call_handle_close)
697 ACE_TRACE ("ACE_Select_Reactor_T::cancel_timer");
698 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
700 if ((this->timer_queue_ != 0) && (handler != 0))
701 return this->timer_queue_->cancel (handler, dont_call_handle_close);
702 else
703 return 0;
706 template <class ACE_SELECT_REACTOR_TOKEN> int
707 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::cancel_timer (long timer_id,
708 const void **arg,
709 int dont_call_handle_close)
711 ACE_TRACE ("ACE_Select_Reactor_T::cancel_timer");
712 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
714 if (this->timer_queue_ != 0)
715 return this->timer_queue_->cancel (timer_id,
716 arg,
717 dont_call_handle_close);
718 else
719 return 0;
722 template <class ACE_SELECT_REACTOR_TOKEN> long
723 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::schedule_timer
724 (ACE_Event_Handler *handler,
725 const void *arg,
726 const ACE_Time_Value &delay_time,
727 const ACE_Time_Value &interval)
729 ACE_TRACE ("ACE_Select_Reactor_T::schedule_timer");
730 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
732 if (0 != this->timer_queue_)
733 return this->timer_queue_->schedule
734 (handler,
735 arg,
736 timer_queue_->gettimeofday () + delay_time,
737 interval);
739 errno = ESHUTDOWN;
740 return -1;
743 template <class ACE_SELECT_REACTOR_TOKEN> int
744 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::reset_timer_interval
745 (long timer_id,
746 const ACE_Time_Value &interval)
748 ACE_TRACE ("ACE_Select_Reactor_T::reset_timer_interval");
749 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
751 if (0 != this->timer_queue_)
753 return this->timer_queue_->reset_interval (timer_id, interval);
756 errno = ESHUTDOWN;
757 return -1;
760 // Main event loop driver that blocks for <max_wait_time> before
761 // returning (will return earlier if I/O or signal events occur).
763 template <class ACE_SELECT_REACTOR_TOKEN> int
764 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::handle_events
765 (ACE_Time_Value &max_wait_time)
767 ACE_TRACE ("ACE_Select_Reactor_T::handle_events");
769 return this->handle_events (&max_wait_time);
772 template <class ACE_SELECT_REACTOR_TOKEN> int
773 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::handle_error ()
775 ACE_TRACE ("ACE_Select_Reactor_T::handle_error");
776 #if defined (ACE_LINUX) && defined (ERESTARTNOHAND)
777 int const error = errno; // Avoid multiple TSS accesses.
778 if (error == EINTR || error == ERESTARTNOHAND)
779 return this->restart_;
780 #else
781 if (errno == EINTR)
782 return this->restart_;
783 #endif /* ACE_LINUX && ERESTARTNOHAND */
784 #if defined (__MVS__) || defined (ACE_WIN32) || defined (ACE_VXWORKS)
785 // On MVS Open Edition and Win32, there can be a number of failure
786 // codes on a bad socket, so check_handles on anything other than
787 // EINTR. VxWorks doesn't even bother to always set errno on error
788 // in select (specifically, it doesn't return EBADF for bad FDs).
789 else
790 return this->check_handles ();
791 #else
792 else if (errno == EBADF)
793 return this->check_handles ();
794 else
795 return -1;
796 #endif /* __MVS__ || ACE_WIN32 */
799 template <class ACE_SELECT_REACTOR_TOKEN> void
800 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::notify_handle
801 (ACE_HANDLE handle,
802 ACE_Reactor_Mask mask,
803 ACE_Handle_Set &ready_mask,
804 ACE_Event_Handler *event_handler,
805 ACE_EH_PTMF ptmf)
807 ACE_TRACE ("ACE_Select_Reactor_T::notify_handle");
808 // Check for removed handlers.
809 if (event_handler == 0)
810 return;
812 bool const reference_counting_required =
813 event_handler->reference_counting_policy ().value () ==
814 ACE_Event_Handler::Reference_Counting_Policy::ENABLED;
816 // Call add_reference() if needed.
817 if (reference_counting_required)
819 event_handler->add_reference ();
822 int const status = (event_handler->*ptmf) (handle);
824 if (status < 0)
825 this->remove_handler_i (handle, mask);
826 else if (status > 0)
827 ready_mask.set_bit (handle);
829 // Call remove_reference() if needed.
830 if (reference_counting_required)
831 event_handler->remove_reference ();
834 // Perform GET, CLR, SET, and ADD operations on the select()
835 // Handle_Sets.
837 // GET = 1, Retrieve current value
838 // SET = 2, Set value of bits to new mask (changes the entire mask)
839 // ADD = 3, Bitwise "or" the value into the mask (only changes
840 // enabled bits)
841 // CLR = 4 Bitwise "and" the negation of the value out of the mask
842 // (only changes enabled bits)
844 // Returns the original mask.
846 template <class ACE_SELECT_REACTOR_TOKEN> int
847 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::mask_ops
848 (ACE_HANDLE handle,
849 ACE_Reactor_Mask mask,
850 int ops)
852 ACE_TRACE ("ACE_Select_Reactor_T::mask_ops");
853 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1));
855 // If the handle is not suspended, then set the ops on the
856 // <wait_set_>, otherwise set the <suspend_set_>.
858 if (this->is_suspended_i (handle))
859 return this->bit_ops (handle, mask, this->suspend_set_, ops);
860 else
861 return this->bit_ops (handle, mask, this->wait_set_, ops);
864 template <class ACE_SELECT_REACTOR_TOKEN> ACE_Event_Handler *
865 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::find_handler_i
866 (ACE_HANDLE handle)
868 ACE_TRACE ("ACE_Select_Reactor_T::find_handler_i");
870 ACE_Event_Handler *event_handler = this->handler_rep_.find (handle);
872 if (event_handler)
874 event_handler->add_reference ();
877 return event_handler;
880 // Must be called with locks held.
882 template <class ACE_SELECT_REACTOR_TOKEN> int
883 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::handler_i
884 (ACE_HANDLE handle,
885 ACE_Reactor_Mask mask,
886 ACE_Event_Handler **eh)
888 ACE_TRACE ("ACE_Select_Reactor_T::handler_i");
889 ACE_Event_Handler *event_handler = this->handler_rep_.find (handle);
891 if (event_handler == 0)
892 return -1;
893 else
895 if ((ACE_BIT_ENABLED (mask, ACE_Event_Handler::READ_MASK)
896 || ACE_BIT_ENABLED (mask, ACE_Event_Handler::ACCEPT_MASK))
897 && this->wait_set_.rd_mask_.is_set (handle) == 0)
898 return -1;
899 if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::WRITE_MASK)
900 && this->wait_set_.wr_mask_.is_set (handle) == 0)
901 return -1;
902 if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::EXCEPT_MASK)
903 && this->wait_set_.ex_mask_.is_set (handle) == 0)
904 return -1;
907 if (eh != 0)
909 *eh = event_handler;
910 event_handler->add_reference ();
913 return 0;
916 // Must be called with locks held
918 template <class ACE_SELECT_REACTOR_TOKEN> int
919 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::resume_i (ACE_HANDLE handle)
921 ACE_TRACE ("ACE_Select_Reactor_T::resume_i");
922 if (this->handler_rep_.find (handle) == 0)
923 return -1;
925 if (this->suspend_set_.rd_mask_.is_set (handle))
927 this->wait_set_.rd_mask_.set_bit (handle);
928 this->suspend_set_.rd_mask_.clr_bit (handle);
930 if (this->suspend_set_.wr_mask_.is_set (handle))
932 this->wait_set_.wr_mask_.set_bit (handle);
933 this->suspend_set_.wr_mask_.clr_bit (handle);
935 if (this->suspend_set_.ex_mask_.is_set (handle))
937 this->wait_set_.ex_mask_.set_bit (handle);
938 this->suspend_set_.ex_mask_.clr_bit (handle);
940 return 0;
943 // Must be called with locks held
945 template <class ACE_SELECT_REACTOR_TOKEN> int
946 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::suspend_i (ACE_HANDLE handle)
948 ACE_TRACE ("ACE_Select_Reactor_T::suspend_i");
949 if (this->handler_rep_.find (handle) == 0)
950 return -1;
952 if (this->wait_set_.rd_mask_.is_set (handle))
954 this->suspend_set_.rd_mask_.set_bit (handle);
955 this->wait_set_.rd_mask_.clr_bit (handle);
957 if (this->wait_set_.wr_mask_.is_set (handle))
959 this->suspend_set_.wr_mask_.set_bit (handle);
960 this->wait_set_.wr_mask_.clr_bit (handle);
962 if (this->wait_set_.ex_mask_.is_set (handle))
964 this->suspend_set_.ex_mask_.set_bit (handle);
965 this->wait_set_.ex_mask_.clr_bit (handle);
968 // Kobi: we need to remove that handle from the
969 // dispatch set as well. We use that function with all the relevant
970 // masks - rd/wr/ex - all the mask. it is completely suspended
971 this->clear_dispatch_mask (handle, ACE_Event_Handler::RWE_MASK);
972 return 0;
975 // Must be called with locks held
977 template <class ACE_SELECT_REACTOR_TOKEN> int
978 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::is_suspended_i (ACE_HANDLE handle)
980 ACE_TRACE ("ACE_Select_Reactor_T::is_suspended_i");
981 if (this->handler_rep_.find (handle) == 0)
982 return 0;
984 return this->suspend_set_.rd_mask_.is_set (handle) ||
985 this->suspend_set_.wr_mask_.is_set (handle) ||
986 this->suspend_set_.ex_mask_.is_set (handle);
989 // Must be called with locks held
991 template <class ACE_SELECT_REACTOR_TOKEN> int
992 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::register_handler_i
993 (ACE_HANDLE handle,
994 ACE_Event_Handler *event_handler,
995 ACE_Reactor_Mask mask)
997 ACE_TRACE ("ACE_Select_Reactor_T::register_handler_i");
999 // Insert the <handle, event_handle> tuple into the Handler
1000 // Repository.
1001 return this->handler_rep_.bind (handle, event_handler, mask);
1004 template <class ACE_SELECT_REACTOR_TOKEN> int
1005 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::remove_handler_i
1006 (ACE_HANDLE handle,
1007 ACE_Reactor_Mask mask)
1009 ACE_TRACE ("ACE_Select_Reactor_T::remove_handler_i");
1011 // Unbind this handle.
1012 return this->handler_rep_.unbind (handle, mask);
1015 template <class ACE_SELECT_REACTOR_TOKEN> int
1016 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::work_pending
1017 (const ACE_Time_Value &max_wait_time)
1019 ACE_TRACE ("ACE_Select_Reactor_T::work_pending");
1021 ACE_Time_Value mwt (max_wait_time);
1022 ACE_MT (ACE_Countdown_Time countdown (&mwt));
1024 ACE_MT (ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN,
1025 ace_mon,
1026 this->token_,
1027 -1));
1029 if (this->deactivated_)
1030 return 0;
1032 // Update the countdown to reflect time waiting for the mutex.
1033 ACE_MT (countdown.update ());
1035 ACE_Time_Value timer_buf (0);
1036 ACE_Time_Value *this_timeout =
1037 this->timer_queue_->calculate_timeout (&mwt, &timer_buf);
1039 // Check if we have timers to fire.
1040 bool const timers_pending =
1041 (this_timeout != 0 && *this_timeout != mwt ? true : false);
1043 #ifdef ACE_WIN32
1044 // This arg is ignored on Windows and causes pointer truncation
1045 // warnings on 64-bit compiles.
1046 int const width = 0;
1047 #else
1048 int const width = this->handler_rep_.max_handlep1 ();
1049 #endif /* ACE_WIN32 */
1051 ACE_Select_Reactor_Handle_Set fd_set;
1052 fd_set.rd_mask_ = this->wait_set_.rd_mask_;
1053 fd_set.wr_mask_ = this->wait_set_.wr_mask_;
1054 fd_set.ex_mask_ = this->wait_set_.ex_mask_;
1056 int const nfds = ACE_OS::select (width,
1057 fd_set.rd_mask_,
1058 fd_set.wr_mask_,
1059 fd_set.ex_mask_,
1060 this_timeout);
1062 // If timers are pending, override any timeout from the select()
1063 // call.
1064 return (nfds == 0 && timers_pending ? 1 : nfds);
1067 // Must be called with lock held.
1069 template <class ACE_SELECT_REACTOR_TOKEN> int
1070 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::wait_for_multiple_events
1071 (ACE_Select_Reactor_Handle_Set &dispatch_set,
1072 ACE_Time_Value *max_wait_time)
1074 ACE_TRACE ("ACE_Select_Reactor_T::wait_for_multiple_events");
1075 ACE_Time_Value timer_buf (0);
1076 ACE_Time_Value *this_timeout = 0;
1078 int number_of_active_handles = this->any_ready (dispatch_set);
1080 // If there are any bits enabled in the <ready_set_> then we'll
1081 // handle those first, otherwise we'll block in <select>.
1083 if (number_of_active_handles == 0)
1087 if (this->timer_queue_ == 0)
1088 return 0;
1090 this_timeout =
1091 this->timer_queue_->calculate_timeout (max_wait_time,
1092 &timer_buf);
1093 #ifdef ACE_WIN32
1094 // This arg is ignored on Windows and causes pointer
1095 // truncation warnings on 64-bit compiles.
1096 int const width = 0;
1097 #else
1098 int const width = this->handler_rep_.max_handlep1 ();
1099 #endif /* ACE_WIN32 */
1101 dispatch_set.rd_mask_ = this->wait_set_.rd_mask_;
1102 dispatch_set.wr_mask_ = this->wait_set_.wr_mask_;
1103 dispatch_set.ex_mask_ = this->wait_set_.ex_mask_;
1104 number_of_active_handles = ACE_OS::select (width,
1105 dispatch_set.rd_mask_,
1106 dispatch_set.wr_mask_,
1107 dispatch_set.ex_mask_,
1108 this_timeout);
1110 while (number_of_active_handles == -1 && this->handle_error () > 0);
1112 if (number_of_active_handles > 0)
1114 #if !defined (ACE_WIN32)
1115 // Resynchronize the fd_sets so their "max" is set properly.
1116 dispatch_set.rd_mask_.sync (this->handler_rep_.max_handlep1 ());
1117 dispatch_set.wr_mask_.sync (this->handler_rep_.max_handlep1 ());
1118 dispatch_set.ex_mask_.sync (this->handler_rep_.max_handlep1 ());
1119 #endif /* ACE_WIN32 */
1121 else if (number_of_active_handles == -1)
1123 // Normally, select() will reset the bits in dispatch_set
1124 // so that only those filed descriptors that are ready will
1125 // have bits set. However, when an error occurs, the bit
1126 // set remains as it was when the select call was first made.
1127 // Thus, we now have a dispatch_set that has every file
1128 // descriptor that was originally waited for, which is not
1129 // correct. We must clear all the bit sets because we
1130 // have no idea if any of the file descriptors is ready.
1132 // NOTE: We dont have a test case to reproduce this
1133 // problem. But pleae dont ignore this and remove it off.
1134 dispatch_set.rd_mask_.reset ();
1135 dispatch_set.wr_mask_.reset ();
1136 dispatch_set.ex_mask_.reset ();
1140 // Return the number of events to dispatch.
1141 return number_of_active_handles;
1144 template <class ACE_SELECT_REACTOR_TOKEN> int
1145 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::dispatch_timer_handlers
1146 (int &number_of_handlers_dispatched)
1148 number_of_handlers_dispatched += this->timer_queue_->expire ();
1150 return 0;
1153 template <class ACE_SELECT_REACTOR_TOKEN> int
1154 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::dispatch_notification_handlers
1155 (ACE_Select_Reactor_Handle_Set &dispatch_set,
1156 int &number_of_active_handles,
1157 int &number_of_handlers_dispatched)
1159 // Check to see if the ACE_HANDLE associated with the
1160 // Select_Reactor's notify hook is enabled. If so, it means that
1161 // one or more other threads are trying to update the
1162 // ACE_Select_Reactor_T's internal tables or the notify pipe is
1163 // enabled. We'll handle all these threads and notifications, and
1164 // then break out to continue the event loop.
1165 int const n =
1166 this->notify_handler_->dispatch_notifications (number_of_active_handles,
1167 dispatch_set.rd_mask_);
1169 if (n == -1)
1170 return -1;
1171 else
1173 number_of_handlers_dispatched += n;
1174 number_of_active_handles -= n;
1177 // Same as dispatch_timer_handlers
1178 // No need to do anything with the state changed. That is because
1179 // unbind already handles the case where someone unregister some
1180 // kind of handle and unbind it. (::unbind calls the function
1181 // state_changed () to reflect ant change with that)
1182 // return this->state_changed_ ? -1 : 0;
1183 return 0;
1186 template <class ACE_SELECT_REACTOR_TOKEN> int
1187 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::dispatch_io_set
1188 (int number_of_active_handles,
1189 int &number_of_handlers_dispatched,
1190 int mask,
1191 ACE_Handle_Set &dispatch_mask,
1192 ACE_Handle_Set &ready_mask,
1193 ACE_EH_PTMF callback)
1195 ACE_TRACE ("ACE_Select_Reactor_T::dispatch_io_set");
1196 ACE_HANDLE handle;
1198 ACE_Handle_Set_Iterator handle_iter (dispatch_mask);
1200 while ((handle = handle_iter ()) != ACE_INVALID_HANDLE &&
1201 number_of_handlers_dispatched < number_of_active_handles)
1203 ++number_of_handlers_dispatched;
1205 this->notify_handle (handle,
1206 mask,
1207 ready_mask,
1208 this->handler_rep_.find (handle),
1209 callback);
1211 // clear the bit from that dispatch mask,
1212 // so when we need to restart the iteration (rebuilding the iterator...)
1213 // we will not dispatch the already dispatched handlers
1214 this->clear_dispatch_mask (handle, mask);
1216 if (this->state_changed_)
1218 handle_iter.reset_state ();
1219 this->state_changed_ = false;
1223 return 0;
1226 template <class ACE_SELECT_REACTOR_TOKEN> int
1227 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::dispatch_io_handlers
1228 (ACE_Select_Reactor_Handle_Set &dispatch_set,
1229 int &number_of_active_handles,
1230 int &number_of_handlers_dispatched)
1232 ACE_TRACE ("ACE_Select_Reactor_T::dispatch_io_handlers");
1234 // Handle output events (this code needs to come first to handle the
1235 // obscure case of piggy-backed data coming along with the final
1236 // handshake message of a nonblocking connection).
1238 if (this->dispatch_io_set (number_of_active_handles,
1239 number_of_handlers_dispatched,
1240 ACE_Event_Handler::WRITE_MASK,
1241 dispatch_set.wr_mask_,
1242 this->ready_set_.wr_mask_,
1243 &ACE_Event_Handler::handle_output) == -1)
1245 number_of_active_handles -= number_of_handlers_dispatched;
1246 return -1;
1249 // ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_Select_Reactor_T::dispatch - EXCEPT\n")));
1250 if (this->dispatch_io_set (number_of_active_handles,
1251 number_of_handlers_dispatched,
1252 ACE_Event_Handler::EXCEPT_MASK,
1253 dispatch_set.ex_mask_,
1254 this->ready_set_.ex_mask_,
1255 &ACE_Event_Handler::handle_exception) == -1)
1257 number_of_active_handles -= number_of_handlers_dispatched;
1258 return -1;
1261 // ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE_Select_Reactor_T::dispatch - READ\n")));
1262 if (this->dispatch_io_set (number_of_active_handles,
1263 number_of_handlers_dispatched,
1264 ACE_Event_Handler::READ_MASK,
1265 dispatch_set.rd_mask_,
1266 this->ready_set_.rd_mask_,
1267 &ACE_Event_Handler::handle_input) == -1)
1269 number_of_active_handles -= number_of_handlers_dispatched;
1270 return -1;
1273 number_of_active_handles -= number_of_handlers_dispatched;
1274 return 0;
1277 template <class ACE_SELECT_REACTOR_TOKEN> int
1278 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::dispatch
1279 (int active_handle_count,
1280 ACE_Select_Reactor_Handle_Set &dispatch_set)
1282 ACE_TRACE ("ACE_Select_Reactor_T::dispatch");
1284 int io_handlers_dispatched = 0;
1285 int other_handlers_dispatched = 0;
1286 int signal_occurred = 0;
1287 // The following do/while loop keeps dispatching as long as there
1288 // are still active handles. Note that the only way we should ever
1289 // iterate more than once through this loop is if signals occur
1290 // while we're dispatching other handlers.
1294 // We expect that the loop will decrease the number of active
1295 // handles in each iteration. If it does not, then something is
1296 // inconsistent in the state of the Reactor and we should avoid
1297 // the loop. Please read the comments on bug 2540 for more
1298 // details.
1299 int initial_handle_count = active_handle_count;
1301 // Note that we keep track of changes to our state. If any of
1302 // the dispatch_*() methods below return -1 it means that the
1303 // <wait_set_> state has changed as the result of an
1304 // <ACE_Event_Handler> being dispatched. This means that we
1305 // need to bail out and rerun the select() loop since our
1306 // existing notion of handles in <dispatch_set> may no longer be
1307 // correct.
1309 // In the beginning, our state starts out unchanged. After
1310 // every iteration (i.e., due to signals), our state starts out
1311 // unchanged again.
1313 this->state_changed_ = false;
1315 // Perform the Template Method for dispatching all the handlers.
1317 // First check for interrupts.
1318 if (active_handle_count == -1)
1320 // Bail out -- we got here since <select> was interrupted.
1321 if (ACE_Sig_Handler::sig_pending () != 0)
1323 ACE_Sig_Handler::sig_pending (0);
1325 // If any HANDLES in the <ready_set_> are activated as a
1326 // result of signals they should be dispatched since
1327 // they may be time critical...
1328 active_handle_count = this->any_ready (dispatch_set);
1330 // Record the fact that the Reactor has dispatched a
1331 // handle_signal() method. We need this to return the
1332 // appropriate count below.
1333 signal_occurred = 1;
1335 else
1336 return -1;
1339 // Handle timers early since they may have higher latency
1340 // constraints than I/O handlers. Ideally, the order of
1341 // dispatching should be a strategy...
1342 else if (this->dispatch_timer_handlers (other_handlers_dispatched) == -1)
1343 // State has changed or timer queue has failed, exit loop.
1344 break;
1346 // Check to see if there are no more I/O handles left to
1347 // dispatch AFTER we've handled the timers...
1348 else if (active_handle_count == 0)
1349 return io_handlers_dispatched
1350 + other_handlers_dispatched
1351 + signal_occurred;
1353 // Next dispatch the notification handlers (if there are any to
1354 // dispatch). These are required to handle multi-threads that
1355 // are trying to update the <Reactor>.
1357 else if (this->dispatch_notification_handlers
1358 (dispatch_set,
1359 active_handle_count,
1360 other_handlers_dispatched) == -1)
1361 // State has changed or a serious failure has occurred, so exit
1362 // loop.
1363 break;
1365 // Finally, dispatch the I/O handlers.
1366 else if (this->dispatch_io_handlers
1367 (dispatch_set,
1368 active_handle_count,
1369 io_handlers_dispatched) == -1)
1370 // State has changed, so exit loop.
1371 break;
1373 // if state changed, we need to re-eval active_handle_count,
1374 // so we will not end with an endless loop
1375 if (initial_handle_count == active_handle_count
1376 || this->state_changed_)
1378 active_handle_count = this->any_ready (dispatch_set);
1381 while (active_handle_count > 0);
1383 return io_handlers_dispatched + other_handlers_dispatched + signal_occurred;
1386 template <class ACE_SELECT_REACTOR_TOKEN> int
1387 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::release_token ()
1389 #if defined (ACE_WIN32)
1390 this->token_.release ();
1391 return (int) EXCEPTION_CONTINUE_SEARCH;
1392 #else
1393 return 0;
1394 #endif /* ACE_WIN32 */
1397 template <class ACE_SELECT_REACTOR_TOKEN> int
1398 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::handle_events
1399 (ACE_Time_Value *max_wait_time)
1401 ACE_TRACE ("ACE_Select_Reactor_T::handle_events");
1403 // Stash the current time -- the destructor of this object will
1404 // automatically compute how much time elapsed since this method was
1405 // called.
1406 ACE_Countdown_Time countdown (max_wait_time);
1408 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
1410 ACE_GUARD_RETURN (ACE_SELECT_REACTOR_TOKEN, ace_mon, this->token_, -1);
1412 if (ACE_OS::thr_equal (ACE_Thread::self (), this->owner_) == 0)
1414 errno = EACCES;
1415 return -1;
1417 if (this->deactivated_)
1419 errno = ESHUTDOWN;
1420 return -1;
1423 // Update the countdown to reflect time waiting for the mutex.
1424 countdown.update ();
1425 #else
1426 if (this->deactivated_)
1428 errno = ESHUTDOWN;
1429 return -1;
1431 #endif /* ACE_MT_SAFE */
1433 return this->handle_events_i (max_wait_time);
1436 template <class ACE_SELECT_REACTOR_TOKEN> int
1437 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::handle_events_i
1438 (ACE_Time_Value *max_wait_time)
1440 int result = -1;
1442 ACE_SEH_TRY
1444 // We use the data member dispatch_set_ as the current dispatch
1445 // set.
1447 // We need to start from a clean dispatch_set
1448 this->dispatch_set_.rd_mask_.reset ();
1449 this->dispatch_set_.wr_mask_.reset ();
1450 this->dispatch_set_.ex_mask_.reset ();
1452 int number_of_active_handles =
1453 this->wait_for_multiple_events (this->dispatch_set_,
1454 max_wait_time);
1456 result =
1457 this->dispatch (number_of_active_handles,
1458 this->dispatch_set_);
1460 ACE_SEH_EXCEPT (this->release_token ())
1462 // As it stands now, we catch and then rethrow all Win32
1463 // structured exceptions so that we can make sure to release the
1464 // <token_> lock correctly.
1467 return result;
1470 template <class ACE_SELECT_REACTOR_TOKEN> int
1471 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::check_handles ()
1473 ACE_TRACE ("ACE_Select_Reactor_T::check_handles");
1475 #if defined (ACE_WIN32) || defined (__MVS__) || defined (ACE_VXWORKS)
1476 ACE_Time_Value time_poll = ACE_Time_Value::zero;
1477 ACE_Handle_Set rd_mask;
1478 #endif /* ACE_WIN32 || MVS || ACE_VXWORKS */
1480 int result = 0;
1483 * It's easier to run through the handler repository iterator, but that
1484 * misses handles that are registered on a handler that doesn't implement
1485 * get_handle(). So, build a handle set that's the union of the three
1486 * wait_sets (rd, wrt, ex) and run through that. Bad handles get cleared
1487 * out of all sets.
1489 ACE_HANDLE h;
1490 ACE_Handle_Set check_set (this->wait_set_.rd_mask_);
1491 ACE_Handle_Set_Iterator wr_iter (this->wait_set_.wr_mask_);
1492 while ((h = wr_iter ()) != ACE_INVALID_HANDLE)
1493 check_set.set_bit (h);
1494 ACE_Handle_Set_Iterator ex_iter (this->wait_set_.ex_mask_);
1495 while ((h = ex_iter ()) != ACE_INVALID_HANDLE)
1496 check_set.set_bit (h);
1498 ACE_Handle_Set_Iterator check_iter (check_set);
1499 while ((h = check_iter ()) != ACE_INVALID_HANDLE)
1501 #if defined (ACE_WIN32) || defined (__MVS__) || defined (ACE_VXWORKS)
1502 // Win32 needs to do the check this way because fstat won't work on
1503 // a socket handle. MVS Open Edition needs to do it this way because,
1504 // even though the docs say to check a handle with either select or
1505 // fstat, the fstat method always says the handle is ok.
1506 // pSOS needs to do it this way because file handles and socket handles
1507 // are maintained by separate pieces of the system. VxWorks needs the select
1508 // variant since fstat always returns an error on socket FDs.
1509 rd_mask.set_bit (h);
1511 # if defined (ACE_WIN32)
1512 // This arg is ignored on Windows and causes pointer truncation
1513 // warnings on 64-bit compiles.
1514 int select_width = 0;
1515 # else
1516 int select_width = int (h) + 1;
1517 # endif /* ACE_WIN32 */
1519 if (ACE_OS::select (select_width,
1520 rd_mask, 0, 0,
1521 &time_poll) < 0)
1523 result = 1;
1524 this->remove_handler_i (h, ACE_Event_Handler::ALL_EVENTS_MASK);
1525 this->wait_set_.rd_mask_.clr_bit (h);
1526 this->wait_set_.wr_mask_.clr_bit (h);
1527 this->wait_set_.ex_mask_.clr_bit (h);
1529 rd_mask.clr_bit (h);
1530 #else /* !ACE_WIN32 && !MVS && !VXWORKS */
1531 struct stat temp;
1533 if (ACE_OS::fstat (h, &temp) == -1)
1535 result = 1;
1536 this->remove_handler_i (h, ACE_Event_Handler::ALL_EVENTS_MASK);
1538 #endif /* ACE_WIN32 || MVS */
1541 return result;
1544 template <class ACE_SELECT_REACTOR_TOKEN> void
1545 ACE_Select_Reactor_T<ACE_SELECT_REACTOR_TOKEN>::dump () const
1547 #if defined (ACE_HAS_DUMP)
1548 ACE_TRACE ("ACE_Select_Reactor_T::dump");
1550 ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
1552 this->timer_queue_->dump ();
1553 this->handler_rep_.dump ();
1554 this->signal_handler_->dump ();
1555 ACELIB_DEBUG ((LM_DEBUG,
1556 ACE_TEXT ("delete_signal_handler_ = %d\n"),
1557 this->delete_signal_handler_));
1559 ACE_HANDLE h;
1561 for (ACE_Handle_Set_Iterator handle_iter_wr (this->wait_set_.wr_mask_);
1562 (h = handle_iter_wr ()) != ACE_INVALID_HANDLE;)
1563 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("write_handle = %d\n"), h));
1565 for (ACE_Handle_Set_Iterator handle_iter_rd (this->wait_set_.rd_mask_);
1566 (h = handle_iter_rd ()) != ACE_INVALID_HANDLE;)
1567 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("read_handle = %d\n"), h));
1569 for (ACE_Handle_Set_Iterator handle_iter_ex (this->wait_set_.ex_mask_);
1570 (h = handle_iter_ex ()) != ACE_INVALID_HANDLE;)
1571 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("except_handle = %d\n"), h));
1573 for (ACE_Handle_Set_Iterator handle_iter_wr_ready (this->ready_set_.wr_mask_);
1574 (h = handle_iter_wr_ready ()) != ACE_INVALID_HANDLE;)
1575 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("write_handle_ready = %d\n"), h));
1577 for (ACE_Handle_Set_Iterator handle_iter_rd_ready (this->ready_set_.rd_mask_);
1578 (h = handle_iter_rd_ready ()) != ACE_INVALID_HANDLE;)
1579 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("read_handle_ready = %d\n"), h));
1581 for (ACE_Handle_Set_Iterator handle_iter_ex_ready (this->ready_set_.ex_mask_);
1582 (h = handle_iter_ex_ready ()) != ACE_INVALID_HANDLE;)
1583 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("except_handle_ready = %d\n"), h));
1585 for (ACE_Handle_Set_Iterator handle_iter_su_ready (this->suspend_set_.wr_mask_);
1586 (h = handle_iter_su_ready ()) != ACE_INVALID_HANDLE;)
1587 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("write_handle_suspend = %d\n"), h));
1589 for (ACE_Handle_Set_Iterator handle_iter_su_ready (this->suspend_set_.rd_mask_);
1590 (h = handle_iter_su_ready ()) != ACE_INVALID_HANDLE;)
1591 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("read_handle_suspend = %d\n"), h));
1593 for (ACE_Handle_Set_Iterator handle_iter_su_ready (this->suspend_set_.ex_mask_);
1594 (h = handle_iter_su_ready ()) != ACE_INVALID_HANDLE;)
1595 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("except_handle_suspend = %d\n"), h));
1597 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("restart_ = %d\n"), this->restart_));
1598 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("requeue_position_ = %d\n"), this->requeue_position_));
1599 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("initialized_ = %d\n"), this->initialized_));
1600 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("owner_ = %d\n"), this->owner_));
1602 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
1603 this->notify_handler_->dump ();
1604 this->token_.dump ();
1605 #endif /* ACE_MT_SAFE */
1607 ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
1608 #endif /* ACE_HAS_DUMP */
1611 ACE_END_VERSIONED_NAMESPACE_DECL
1613 #endif /* ACE_SELECT_REACTOR_T_CPP */