1 #include "ace/TkReactor/TkReactor.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_TkReactor
)
10 // Must be called with lock held
11 ACE_TkReactor::ACE_TkReactor (size_t size
,
14 : ACE_Select_Reactor (size
, restart
, h
),
18 // When the ACE_Select_Reactor is constructed it creates the notify
19 // pipe and registers it with the register_handler_i() method. The
20 // TkReactor overloads this method BUT because the
21 // register_handler_i occurs when constructing the base class
22 // ACE_Select_Reactor, the ACE_Select_Reactor register_handler_i()
23 // is called not the TkReactor register_handler_i(). This means
24 // that the notify pipe is registered with the ACE_Select_Reactor
25 // event handling code not the TkReactor and so notfications don't
26 // work. To get around this we simply close and re-opened the
27 // notification handler in the constructor of the TkReactor.
29 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
30 this->notify_handler_
->close ();
31 this->notify_handler_
->open (this, 0);
32 #endif /* ACE_MT_SAFE */
35 ACE_TkReactor::~ACE_TkReactor (void)
37 // Delete the remaining items in the linked list.
41 ACE_TkReactorID
*TkID
= this->ids_
->next_
;
47 // This is just the <wait_for_multiple_events> from ace/Reactor.cpp
48 // but we use the Tk functions to wait for an event, not <select>
51 ACE_TkReactor::wait_for_multiple_events (ACE_Select_Reactor_Handle_Set
&handle_set
,
52 ACE_Time_Value
*max_wait_time
)
54 ACE_TRACE ("ACE_TkReactor::wait_for_multiple_events");
59 max_wait_time
= this->timer_queue_
->calculate_timeout (max_wait_time
);
61 size_t width
= this->handler_rep_
.max_handlep1 ();
62 handle_set
.rd_mask_
= this->wait_set_
.rd_mask_
;
63 handle_set
.wr_mask_
= this->wait_set_
.wr_mask_
;
64 handle_set
.ex_mask_
= this->wait_set_
.ex_mask_
;
65 nfound
= TkWaitForMultipleEvents (width
,
69 } while (nfound
== -1 && this->handle_error () > 0);
73 #if !defined (ACE_WIN32)
74 handle_set
.rd_mask_
.sync (this->handler_rep_
.max_handlep1 ());
75 handle_set
.wr_mask_
.sync (this->handler_rep_
.max_handlep1 ());
76 handle_set
.ex_mask_
.sync (this->handler_rep_
.max_handlep1 ());
77 #endif /* ACE_WIN32 */
79 return nfound
; // Timed out or input available
83 ACE_TkReactor::TimerCallbackProc (ClientData cd
)
85 ACE_TkReactor
*self
= (ACE_TkReactor
*) cd
;
88 // Deal with any timer events
89 ACE_Select_Reactor_Handle_Set handle_set
;
90 self
->dispatch (0, handle_set
);
91 self
->reset_timeout ();
95 * @todo the unused mask argument is probably quite useful, but we
96 * ignore it, why? In fact the following comment probably
98 * This could be made shorter if we know which *kind* of event
99 * we were about to get. Here we use <select> to find out which
100 * one might be available.
103 ACE_TkReactor::InputCallbackProc (ClientData cd
,
106 ACE_TkReactor_Input_Callback
*callback
= (ACE_TkReactor_Input_Callback
*) cd
;
107 ACE_TkReactor
*self
= callback
->reactor_
;
108 ACE_HANDLE handle
= callback
->handle_
;
110 // my copy isn't const.
111 ACE_Time_Value zero
= ACE_Time_Value::zero
;
113 ACE_Select_Reactor_Handle_Set wait_set
;
115 // Deal with one file event.
117 // - read which kind of event
118 if (self
->wait_set_
.rd_mask_
.is_set (handle
))
119 wait_set
.rd_mask_
.set_bit (handle
);
120 if (self
->wait_set_
.wr_mask_
.is_set (handle
))
121 wait_set
.wr_mask_
.set_bit (handle
);
122 if (self
->wait_set_
.ex_mask_
.is_set (handle
))
123 wait_set
.ex_mask_
.set_bit (handle
);
125 int result
= ACE_OS::select (handle
+ 1,
128 wait_set
.ex_mask_
, &zero
);
130 ACE_Select_Reactor_Handle_Set dispatch_set
;
132 // - Use only that one file event (removes events for other files).
135 if (wait_set
.rd_mask_
.is_set (handle
))
136 dispatch_set
.rd_mask_
.set_bit (handle
);
137 if (wait_set
.wr_mask_
.is_set (handle
))
138 dispatch_set
.wr_mask_
.set_bit (handle
);
139 if (wait_set
.ex_mask_
.is_set (handle
))
140 dispatch_set
.ex_mask_
.set_bit (handle
);
142 self
->dispatch (1, dispatch_set
);
147 ACE_TkReactor::TkWaitForMultipleEvents (int width
,
148 ACE_Select_Reactor_Handle_Set
&wait_set
,
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 Tk mechanism to
162 // wait for a single event.
164 // Wait for something to happen.
165 ::Tcl_DoOneEvent (0);
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_TkReactor::register_handler_i (ACE_HANDLE handle
,
181 ACE_Event_Handler
*handler
,
182 ACE_Reactor_Mask mask
)
184 ACE_TRACE ("ACE_TkReactor::register_handler_i");
186 int result
= ACE_Select_Reactor::register_handler_i (handle
,
193 #if !defined ACE_WIN32
194 if (ACE_BIT_ENABLED (mask
, ACE_Event_Handler::READ_MASK
))
195 ACE_SET_BITS (condition
, TK_READABLE
);
196 if (ACE_BIT_ENABLED (mask
, ACE_Event_Handler::WRITE_MASK
))
197 ACE_SET_BITS (condition
, TK_WRITABLE
);
198 if (ACE_BIT_ENABLED (mask
, ACE_Event_Handler::EXCEPT_MASK
))
199 ACE_SET_BITS (condition
, TK_EXCEPTION
);
200 if (ACE_BIT_ENABLED (mask
, ACE_Event_Handler::ACCEPT_MASK
))
201 ACE_SET_BITS (condition
, TK_READABLE
);
202 if (ACE_BIT_ENABLED (mask
, ACE_Event_Handler::CONNECT_MASK
)){
203 ACE_SET_BITS (condition
, TK_READABLE
); // connected, you may write
204 ACE_SET_BITS (condition
, TK_WRITABLE
); // connected, you have data/err
207 if (ACE_BIT_ENABLED (mask
, ACE_Event_Handler::READ_MASK
))
208 ACE_SET_BITS (condition
, TK_READABLE
);
209 if (ACE_BIT_ENABLED (mask
, ACE_Event_Handler::WRITE_MASK
))
210 ACE_SET_BITS (condition
, TK_WRITABLE
);
211 if (ACE_BIT_ENABLED (mask
, ACE_Event_Handler::EXCEPT_MASK
))
212 ACE_NOTSUP_RETURN(-1);
213 if (ACE_BIT_ENABLED (mask
, ACE_Event_Handler::ACCEPT_MASK
))
214 ACE_SET_BITS (condition
, TK_READABLE
);
215 if (ACE_BIT_ENABLED (mask
, ACE_Event_Handler::CONNECT_MASK
)){
216 ACE_SET_BITS (condition
, TK_READABLE
); // connected, you may write
217 ACE_SET_BITS (condition
, TK_WRITABLE
); // connected, you have data/err
219 #endif /* !ACE_WIN32 */
223 ACE_TkReactorID
*TkID
= this->ids_
;
227 if (TkID
->handle_
== handle
)
229 ::Tk_DeleteFileHandler (TkID
->handle_
);
231 ACE_TkReactor_Input_Callback
*callback
;
232 ACE_NEW_RETURN (callback
,
233 ACE_TkReactor_Input_Callback
,
235 callback
->reactor_
= this;
236 callback
->handle_
= handle
;
237 ::Tk_CreateFileHandler ((int) handle
,
240 (ClientData
) callback
);
247 ACE_NEW_RETURN (TkID
,
250 TkID
->next_
= this->ids_
;
251 TkID
->handle_
= handle
;
252 ACE_TkReactor_Input_Callback
*callback
;
253 ACE_NEW_RETURN (callback
,
254 ACE_TkReactor_Input_Callback
,
256 callback
->reactor_
= this;
257 callback
->handle_
= handle
;
259 ::Tk_CreateFileHandler ((int) handle
,
262 (ClientData
) callback
);
269 ACE_TkReactor::register_handler_i (const ACE_Handle_Set
&handles
,
270 ACE_Event_Handler
*handler
,
271 ACE_Reactor_Mask mask
)
273 return ACE_Select_Reactor::register_handler_i (handles
,
279 ACE_TkReactor::remove_handler_i (ACE_HANDLE handle
,
280 ACE_Reactor_Mask mask
)
282 ACE_TRACE ("ACE_TkReactor::remove_handler_i");
284 // In the registration phase we registered first with
285 // ACE_Select_Reactor and then with X. Now we are now doing things
288 // First clean up the corresponding X11Input.
289 this->remove_TkFileHandler (handle
);
291 // Now let the reactor do its work.
292 return ACE_Select_Reactor::remove_handler_i (handle
,
297 ACE_TkReactor::remove_TkFileHandler (ACE_HANDLE handle
)
299 ACE_TRACE ("ACE_TkReactor::remove_TkFileHandler");
301 ACE_TkReactorID
*TkID
= this->ids_
;
305 if (TkID
->handle_
== handle
)
307 ::Tk_DeleteFileHandler (TkID
->handle_
);
308 this->ids_
= TkID
->next_
;
313 ACE_TkReactorID
*NextID
= TkID
->next_
;
317 if (NextID
->handle_
== handle
)
319 ::Tk_DeleteFileHandler (NextID
->handle_
);
320 TkID
->next_
= NextID
->next_
;
327 NextID
= NextID
->next_
;
334 ACE_TkReactor::remove_handler_i (const ACE_Handle_Set
&handles
,
335 ACE_Reactor_Mask mask
)
337 return ACE_Select_Reactor::remove_handler_i (handles
,
341 // The following functions ensure that there is an Tk timeout for the
342 // first timeout in the Reactor's Timer_Queue.
345 ACE_TkReactor::reset_timeout (void)
348 ::Tk_DeleteTimerHandler (this->timeout_
);
351 ACE_Time_Value
*max_wait_time
=
352 this->timer_queue_
->calculate_timeout (0);
355 timeout_
= ::Tk_CreateTimerHandler (max_wait_time
->msec (),
361 ACE_TkReactor::reset_timer_interval
363 const ACE_Time_Value
&interval
)
365 ACE_TRACE ("ACE_TkReactor::reset_timer_interval");
366 ACE_MT (ACE_GUARD_RETURN (ACE_Select_Reactor_Token
, ace_mon
, this->token_
, -1));
368 int result
= ACE_Select_Reactor::timer_queue_
->reset_interval
376 this->reset_timeout ();
382 ACE_TkReactor::schedule_timer (ACE_Event_Handler
*event_handler
,
384 const ACE_Time_Value
&delay
,
385 const ACE_Time_Value
&interval
)
387 ACE_TRACE ("ACE_TkReactor::schedule_timer");
388 ACE_MT (ACE_GUARD_RETURN (ACE_Select_Reactor_Token
, ace_mon
, this->token_
, -1));
390 long result
= ACE_Select_Reactor::schedule_timer (event_handler
,
398 this->reset_timeout ();
404 ACE_TkReactor::cancel_timer (ACE_Event_Handler
*handler
,
405 int dont_call_handle_close
)
407 ACE_TRACE ("ACE_TkReactor::cancel_timer");
409 if (ACE_Select_Reactor::cancel_timer (handler
,
410 dont_call_handle_close
) == -1)
414 this->reset_timeout ();
420 ACE_TkReactor::cancel_timer (long timer_id
,
422 int dont_call_handle_close
)
424 ACE_TRACE ("ACE_TkReactor::cancel_timer");
426 if (ACE_Select_Reactor::cancel_timer (timer_id
,
428 dont_call_handle_close
) == -1)
432 this->reset_timeout ();
437 ACE_END_VERSIONED_NAMESPACE_DECL