Cleanup ACE_HAS_PTHREAD_SIGMASK_PROTOTYPE, all platforms support it so far as I can...
[ACE_TAO.git] / ACE / ace / XtReactor / XtReactor.cpp
blob3be96043882626fc63676075367ba775037a9c02
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,
12 size_t size,
13 bool restart,
14 ACE_Sig_Handler *h)
15 : ACE_Select_Reactor (size, restart, h),
16 context_ (context),
17 ids_ (0),
18 timeout_ (0)
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.
41 while (this->ids_)
43 ACE_XtReactorID *XtID = this->ids_->next_;
44 delete this->ids_;
45 this->ids_ = XtID;
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>
52 int
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");
57 int nfound;
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,
68 handle_set,
69 max_wait_time);
70 } while (nfound == -1 && this->handle_error () > 0);
72 if (nfound > 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
83 void
84 ACE_XtReactor::TimerCallbackProc (XtPointer closure, XtIntervalId * /* id */)
86 ACE_XtReactor *self = (ACE_XtReactor *) closure;
87 self->timeout_ = 0;
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
97 // available.
99 void
100 ACE_XtReactor::InputCallbackProc (XtPointer closure,
101 int *source,
102 XtInputId *)
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,
123 wait_set.rd_mask_,
124 wait_set.wr_mask_,
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).
130 if (result > 0)
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,
146 ACE_Time_Value *)
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,
155 temp_set.rd_mask_,
156 temp_set.wr_mask_,
157 temp_set.ex_mask_,
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
171 // <select>.
172 return ACE_OS::select (width,
173 wait_set.rd_mask_,
174 wait_set.wr_mask_,
175 wait_set.ex_mask_,
176 (ACE_Time_Value *) &ACE_Time_Value::zero);
179 XtAppContext
180 ACE_XtReactor::context () const
182 return this->context_;
185 void
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,
208 handler, mask);
209 if (result == -1)
210 return -1;
212 synchronize_XtInput (handle);
213 return 0;
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,
222 handler,
223 mask);
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,
233 mask);
234 if (result == -1)
235 return -1;
237 synchronize_XtInput (handle);
238 return 0;
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,
246 mask);
250 ACE_XtReactor::suspend_i (ACE_HANDLE handle)
252 ACE_TRACE ("ACE_XtReactor::suspend_i");
254 int result = ACE_Select_Reactor::suspend_i (handle);
256 if (result == -1)
257 return -1;
259 synchronize_XtInput (handle);
260 return 0;
264 ACE_XtReactor::resume_i (ACE_HANDLE handle)
266 ACE_TRACE ("ACE_XtReactor::resume_i");
268 int result = ACE_Select_Reactor::resume_i (handle);
270 if (result == -1)
271 return -1;
273 synchronize_XtInput (handle);
274 return 0;
277 void
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.
293 if (*XtID)
294 ::XtRemoveInput ((*XtID)->id_);
296 int condition = compute_Xt_condition (handle);
298 if (condition == 0) // No input handler needed.
300 if (*XtID)
302 // Remove linked list entry.
303 ACE_XtReactorID *toDelete = *XtID;
304 *XtID = (*XtID)->next_;
305 delete toDelete;
307 return;
310 if (*XtID == 0)
312 // Create new node.
313 ACE_XtReactorID *tmp = new ACE_XtReactorID;
314 tmp->next_ = this->ids_;
315 tmp->handle_ = handle;
316 this->ids_ = tmp;
317 XtID = &(this->ids_);
320 // Finally, add input handler.
321 (*XtID)->id_ = ::XtAppAddInput (this->context_,
322 (int) handle,
323 reinterpret_cast <XtPointer> (condition),
324 InputCallbackProc,
325 (XtPointer) this);
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
335 // or -1.
336 int mask =this->bit_ops(handle,
338 this->wait_set_,
339 ACE_Reactor::GET_MASK);
341 if (mask == -1) // No active mask.
342 return 0;
344 int condition = 0;
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);
353 #else
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 */
362 return condition;
365 // The following functions ensure that there is an Xt timeout for the
366 // first timeout in the Reactor's Timer_Queue.
368 void
369 ACE_XtReactor::reset_timeout ()
371 // Make sure we have a valid context
372 ACE_ASSERT (this->context_ != 0);
374 if (timeout_)
375 ::XtRemoveTimeOut (timeout_);
376 timeout_ = 0;
378 ACE_Time_Value *max_wait_time =
379 this->timer_queue_->calculate_timeout (0);
381 if (max_wait_time)
382 timeout_ = ::XtAppAddTimeOut (this->context_,
383 max_wait_time->msec (),
384 TimerCallbackProc,
385 (XtPointer) this);
389 ACE_XtReactor::reset_timer_interval
390 (long timer_id,
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
397 (timer_id,
398 interval);
400 if (result == -1)
401 return -1;
402 else
404 this->reset_timeout ();
405 return result;
409 long
410 ACE_XtReactor::schedule_timer (ACE_Event_Handler *event_handler,
411 const void *arg,
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,
419 arg,
420 delay,
421 interval);
422 if (result == -1)
423 return -1;
424 else
426 this->reset_timeout ();
427 return result;
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)
439 return -1;
440 else
442 this->reset_timeout ();
443 return 0;
448 ACE_XtReactor::cancel_timer (long timer_id,
449 const void **arg,
450 int dont_call_handle_close)
452 ACE_TRACE ("ACE_XtReactor::cancel_timer");
454 if (ACE_Select_Reactor::cancel_timer (timer_id,
455 arg,
456 dont_call_handle_close) == -1)
457 return -1;
458 else
460 this->reset_timeout ();
461 return 0;
465 ACE_END_VERSIONED_NAMESPACE_DECL