1 #include "ace/XtReactor/XtReactor.h"
3 #include "ace/SOCK_Acceptor.h"
4 #include "ace/SOCK_Connector.h"
6 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
8 ACE_ALLOC_HOOK_DEFINE (ACE_XtReactor
)
10 // Must be called with lock held
11 ACE_XtReactor::ACE_XtReactor (XtAppContext context
,
15 : ACE_Select_Reactor (size
, restart
, h
),
20 // When the ACE_Select_Reactor is constructed it creates the notify
21 // pipe and registers it with the register_handler_i() method. The
22 // XtReactor overloads this method BUT because the
23 // register_handler_i occurs when constructing the base class
24 // ACE_Select_Reactor, the ACE_Select_Reactor register_handler_i()
25 // is called not the XtReactor register_handler_i(). This means
26 // that the notify pipe is registered with the ACE_Select_Reactor
27 // event handling code not the XtReactor and so notfications don't
28 // work. To get around this we simply close and re-opened the
29 // notification handler in the constructor of the XtReactor.
31 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
32 this->notify_handler_
->close ();
33 this->notify_handler_
->open (this, 0);
34 #endif /* ACE_MT_SAFE */
37 ACE_XtReactor::~ACE_XtReactor ()
39 // Delete the remaining items in the linked list.
43 ACE_XtReactorID
*XtID
= this->ids_
->next_
;
49 // This is just the <wait_for_multiple_events> from ace/Reactor.cpp
50 // but we use the Xt functions to wait for an event, not <select>
53 ACE_XtReactor::wait_for_multiple_events (ACE_Select_Reactor_Handle_Set
&handle_set
,
54 ACE_Time_Value
*max_wait_time
)
56 ACE_TRACE ("ACE_XtReactor::wait_for_multiple_events");
61 max_wait_time
= this->timer_queue_
->calculate_timeout (max_wait_time
);
63 size_t width
= this->handler_rep_
.max_handlep1 ();
64 handle_set
.rd_mask_
= this->wait_set_
.rd_mask_
;
65 handle_set
.wr_mask_
= this->wait_set_
.wr_mask_
;
66 handle_set
.ex_mask_
= this->wait_set_
.ex_mask_
;
67 nfound
= XtWaitForMultipleEvents (width
,
70 } while (nfound
== -1 && this->handle_error () > 0);
74 #if !defined (ACE_WIN32)
75 handle_set
.rd_mask_
.sync (this->handler_rep_
.max_handlep1 ());
76 handle_set
.wr_mask_
.sync (this->handler_rep_
.max_handlep1 ());
77 handle_set
.ex_mask_
.sync (this->handler_rep_
.max_handlep1 ());
78 #endif /* ACE_WIN32 */
80 return nfound
; // Timed out or input available
84 ACE_XtReactor::TimerCallbackProc (XtPointer closure
, XtIntervalId
* /* id */)
86 ACE_XtReactor
*self
= (ACE_XtReactor
*) closure
;
89 // Deal with any timer events
90 ACE_Select_Reactor_Handle_Set handle_set
;
91 self
->dispatch (0, handle_set
);
92 self
->reset_timeout ();
95 // This could be made shorter if we know which *kind* of event we were
96 // about to get. Here we use <select> to find out which one might be
100 ACE_XtReactor::InputCallbackProc (XtPointer closure
,
104 ACE_XtReactor
*self
= (ACE_XtReactor
*) closure
;
105 ACE_HANDLE handle
= (ACE_HANDLE
) *source
;
107 // my copy isn't const.
108 ACE_Time_Value zero
= ACE_Time_Value::zero
;
110 ACE_Select_Reactor_Handle_Set wait_set
;
112 // Deal with one file event.
114 // - read which kind of event
115 if (self
->wait_set_
.rd_mask_
.is_set (handle
))
116 wait_set
.rd_mask_
.set_bit (handle
);
117 if (self
->wait_set_
.wr_mask_
.is_set (handle
))
118 wait_set
.wr_mask_
.set_bit (handle
);
119 if (self
->wait_set_
.ex_mask_
.is_set (handle
))
120 wait_set
.ex_mask_
.set_bit (handle
);
122 int result
= ACE_OS::select (*source
+ 1,
125 wait_set
.ex_mask_
, &zero
);
127 ACE_Select_Reactor_Handle_Set dispatch_set
;
129 // - Use only that one file event (removes events for other files).
132 if (wait_set
.rd_mask_
.is_set (handle
))
133 dispatch_set
.rd_mask_
.set_bit (handle
);
134 if (wait_set
.wr_mask_
.is_set (handle
))
135 dispatch_set
.wr_mask_
.set_bit (handle
);
136 if (wait_set
.ex_mask_
.is_set (handle
))
137 dispatch_set
.ex_mask_
.set_bit (handle
);
139 self
->dispatch (1, dispatch_set
);
144 ACE_XtReactor::XtWaitForMultipleEvents (int width
,
145 ACE_Select_Reactor_Handle_Set
&wait_set
,
148 // Make sure we have a valid context
149 ACE_ASSERT (this->context_
!= 0);
151 // Check to make sure our handle's are all usable.
152 ACE_Select_Reactor_Handle_Set temp_set
= wait_set
;
154 if (ACE_OS::select (width
,
158 (ACE_Time_Value
*) &ACE_Time_Value::zero
) == -1)
159 return -1; // Bad file arguments...
161 // Instead of waiting using <select>, just use the Xt mechanism to
162 // wait for a single event.
164 // Wait for something to happen.
165 ::XtAppProcessEvent (this->context_
, XtIMAll
);
167 // Reset the width, in case it changed during the upcalls.
168 width
= this->handler_rep_
.max_handlep1 ();
170 // Now actually read the result needed by the <Select_Reactor> using
172 return ACE_OS::select (width
,
176 (ACE_Time_Value
*) &ACE_Time_Value::zero
);
180 ACE_XtReactor::context () const
182 return this->context_
;
186 ACE_XtReactor::context (XtAppContext context
)
188 this->context_
= context
;
192 ACE_XtReactor::register_handler_i (ACE_HANDLE handle
,
193 ACE_Event_Handler
*handler
,
194 ACE_Reactor_Mask mask
)
196 ACE_TRACE ("ACE_XtReactor::register_handler_i");
198 // Make sure we have a valid context
199 ACE_ASSERT (this->context_
!= 0);
201 #if defined ACE_WIN32
202 // Let's handle this special case before we do any real work.
203 if (ACE_BIT_ENABLED (mask
, ACE_Event_Handler::EXCEPT_MASK
))
204 ACE_NOTSUP_RETURN(-1);
205 #endif /* ACE_WIN32 */
207 int result
= ACE_Select_Reactor::register_handler_i (handle
,
212 synchronize_XtInput (handle
);
217 ACE_XtReactor::register_handler_i (const ACE_Handle_Set
&handles
,
218 ACE_Event_Handler
*handler
,
219 ACE_Reactor_Mask mask
)
221 return ACE_Select_Reactor::register_handler_i (handles
,
227 ACE_XtReactor::remove_handler_i (ACE_HANDLE handle
,
228 ACE_Reactor_Mask mask
)
230 ACE_TRACE ("ACE_XtReactor::remove_handler_i");
232 int result
= ACE_Select_Reactor::remove_handler_i (handle
,
237 synchronize_XtInput (handle
);
242 ACE_XtReactor::remove_handler_i (const ACE_Handle_Set
&handles
,
243 ACE_Reactor_Mask mask
)
245 return ACE_Select_Reactor::remove_handler_i (handles
,
250 ACE_XtReactor::suspend_i (ACE_HANDLE handle
)
252 ACE_TRACE ("ACE_XtReactor::suspend_i");
254 int result
= ACE_Select_Reactor::suspend_i (handle
);
259 synchronize_XtInput (handle
);
264 ACE_XtReactor::resume_i (ACE_HANDLE handle
)
266 ACE_TRACE ("ACE_XtReactor::resume_i");
268 int result
= ACE_Select_Reactor::resume_i (handle
);
273 synchronize_XtInput (handle
);
278 ACE_XtReactor::synchronize_XtInput(ACE_HANDLE handle
)
280 ACE_TRACE ("ACE_XtReactor::synchronize_XtInput");
282 // The idea here is to call this function after the base class has
283 // processed the register/remove/suspend/resume_handler request. The
284 // resulting mask is used to find out which XtInput mask we need.
286 // Find existing handler in linked list.
287 ACE_XtReactorID
**XtID
= &(this->ids_
);
289 while (*XtID
&& (*XtID
)->handle_
!= handle
)
290 XtID
= &((*XtID
)->next_
);
292 // Remove existing input handler.
294 ::XtRemoveInput ((*XtID
)->id_
);
296 int condition
= compute_Xt_condition (handle
);
298 if (condition
== 0) // No input handler needed.
302 // Remove linked list entry.
303 ACE_XtReactorID
*toDelete
= *XtID
;
304 *XtID
= (*XtID
)->next_
;
313 ACE_XtReactorID
*tmp
= new ACE_XtReactorID
;
314 tmp
->next_
= this->ids_
;
315 tmp
->handle_
= handle
;
317 XtID
= &(this->ids_
);
320 // Finally, add input handler.
321 (*XtID
)->id_
= ::XtAppAddInput (this->context_
,
323 reinterpret_cast <XtPointer
> (condition
),
329 ACE_XtReactor::compute_Xt_condition(ACE_HANDLE handle
)
331 ACE_TRACE ("ACE_XtReactor::compute_Xt_condition");
333 // Retrieve current wait mask from base class.
334 // The returned value is either a combination of READ/WRITE/EXCEPT_MASK
336 int mask
=this->bit_ops(handle
,
339 ACE_Reactor::GET_MASK
);
341 if (mask
== -1) // No active mask.
346 #if !defined ACE_WIN32
347 if (ACE_BIT_ENABLED (mask
, ACE_Event_Handler::READ_MASK
))
348 ACE_SET_BITS (condition
, XtInputReadMask
);
349 if (ACE_BIT_ENABLED (mask
, ACE_Event_Handler::WRITE_MASK
))
350 ACE_SET_BITS (condition
, XtInputWriteMask
);
351 if (ACE_BIT_ENABLED (mask
, ACE_Event_Handler::EXCEPT_MASK
))
352 ACE_SET_BITS (condition
, XtInputExceptMask
);
354 if (ACE_BIT_ENABLED (mask
, ACE_Event_Handler::READ_MASK
))
355 ACE_SET_BITS (condition
, XtInputReadWinsock
);
356 if (ACE_BIT_ENABLED (mask
, ACE_Event_Handler::WRITE_MASK
))
357 ACE_SET_BITS (condition
, XtInputWriteWinsock
);
358 // EXCEPT_MASK is not supported for WIN32. As this was
359 // already handled in register_handler_i, no check here.
360 #endif /* !ACE_WIN32 */
365 // The following functions ensure that there is an Xt timeout for the
366 // first timeout in the Reactor's Timer_Queue.
369 ACE_XtReactor::reset_timeout ()
371 // Make sure we have a valid context
372 ACE_ASSERT (this->context_
!= 0);
375 ::XtRemoveTimeOut (timeout_
);
378 ACE_Time_Value
*max_wait_time
=
379 this->timer_queue_
->calculate_timeout (0);
382 timeout_
= ::XtAppAddTimeOut (this->context_
,
383 max_wait_time
->msec (),
389 ACE_XtReactor::reset_timer_interval
391 const ACE_Time_Value
&interval
)
393 ACE_TRACE ("ACE_XtReactor::reset_timer_interval");
394 ACE_MT (ACE_GUARD_RETURN (ACE_Select_Reactor_Token
, ace_mon
, this->token_
, -1));
396 int const result
= ACE_Select_Reactor::timer_queue_
->reset_interval
404 this->reset_timeout ();
410 ACE_XtReactor::schedule_timer (ACE_Event_Handler
*event_handler
,
412 const ACE_Time_Value
&delay
,
413 const ACE_Time_Value
&interval
)
415 ACE_TRACE ("ACE_XtReactor::schedule_timer");
416 ACE_MT (ACE_GUARD_RETURN (ACE_Select_Reactor_Token
, ace_mon
, this->token_
, -1));
418 long const result
= ACE_Select_Reactor::schedule_timer (event_handler
,
426 this->reset_timeout ();
432 ACE_XtReactor::cancel_timer (ACE_Event_Handler
*handler
,
433 int dont_call_handle_close
)
435 ACE_TRACE ("ACE_XtReactor::cancel_timer");
437 if (ACE_Select_Reactor::cancel_timer (handler
,
438 dont_call_handle_close
) == -1)
442 this->reset_timeout ();
448 ACE_XtReactor::cancel_timer (long timer_id
,
450 int dont_call_handle_close
)
452 ACE_TRACE ("ACE_XtReactor::cancel_timer");
454 if (ACE_Select_Reactor::cancel_timer (timer_id
,
456 dont_call_handle_close
) == -1)
460 this->reset_timeout ();
465 ACE_END_VERSIONED_NAMESPACE_DECL