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 ()
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
,
68 } while (nfound
== -1 && this->handle_error () > 0);
72 #if !defined (ACE_WIN32)
73 handle_set
.rd_mask_
.sync (this->handler_rep_
.max_handlep1 ());
74 handle_set
.wr_mask_
.sync (this->handler_rep_
.max_handlep1 ());
75 handle_set
.ex_mask_
.sync (this->handler_rep_
.max_handlep1 ());
76 #endif /* ACE_WIN32 */
78 return nfound
; // Timed out or input available
82 ACE_TkReactor::TimerCallbackProc (ClientData cd
)
84 ACE_TkReactor
*self
= (ACE_TkReactor
*) cd
;
87 // Deal with any timer events
88 ACE_Select_Reactor_Handle_Set handle_set
;
89 self
->dispatch (0, handle_set
);
90 self
->reset_timeout ();
94 * @todo the unused mask argument is probably quite useful, but we
95 * ignore it, why? In fact the following comment probably
97 * This could be made shorter if we know which *kind* of event
98 * we were about to get. Here we use <select> to find out which
99 * one might be available.
102 ACE_TkReactor::InputCallbackProc (ClientData cd
,
105 ACE_TkReactor_Input_Callback
*callback
= (ACE_TkReactor_Input_Callback
*) cd
;
106 ACE_TkReactor
*self
= callback
->reactor_
;
107 ACE_HANDLE handle
= callback
->handle_
;
109 // my copy isn't const.
110 ACE_Time_Value zero
= ACE_Time_Value::zero
;
112 ACE_Select_Reactor_Handle_Set wait_set
;
114 // Deal with one file event.
116 // - read which kind of event
117 if (self
->wait_set_
.rd_mask_
.is_set (handle
))
118 wait_set
.rd_mask_
.set_bit (handle
);
119 if (self
->wait_set_
.wr_mask_
.is_set (handle
))
120 wait_set
.wr_mask_
.set_bit (handle
);
121 if (self
->wait_set_
.ex_mask_
.is_set (handle
))
122 wait_set
.ex_mask_
.set_bit (handle
);
124 int result
= ACE_OS::select (handle
+ 1,
127 wait_set
.ex_mask_
, &zero
);
129 ACE_Select_Reactor_Handle_Set dispatch_set
;
131 // - Use only that one file event (removes events for other files).
134 if (wait_set
.rd_mask_
.is_set (handle
))
135 dispatch_set
.rd_mask_
.set_bit (handle
);
136 if (wait_set
.wr_mask_
.is_set (handle
))
137 dispatch_set
.wr_mask_
.set_bit (handle
);
138 if (wait_set
.ex_mask_
.is_set (handle
))
139 dispatch_set
.ex_mask_
.set_bit (handle
);
141 self
->dispatch (1, dispatch_set
);
146 ACE_TkReactor::TkWaitForMultipleEvents (int width
,
147 ACE_Select_Reactor_Handle_Set
&wait_set
,
150 // Check to make sure our handle's are all usable.
151 ACE_Select_Reactor_Handle_Set temp_set
= wait_set
;
153 if (ACE_OS::select (width
,
157 (ACE_Time_Value
*) &ACE_Time_Value::zero
) == -1)
158 return -1; // Bad file arguments...
160 // Instead of waiting using <select>, just use the Tk mechanism to
161 // wait for a single event.
163 // Wait for something to happen.
164 ::Tcl_DoOneEvent (0);
166 // Reset the width, in case it changed during the upcalls.
167 width
= this->handler_rep_
.max_handlep1 ();
169 // Now actually read the result needed by the <Select_Reactor> using
171 return ACE_OS::select (width
,
175 (ACE_Time_Value
*) &ACE_Time_Value::zero
);
179 ACE_TkReactor::register_handler_i (ACE_HANDLE handle
,
180 ACE_Event_Handler
*handler
,
181 ACE_Reactor_Mask mask
)
183 ACE_TRACE ("ACE_TkReactor::register_handler_i");
185 int result
= ACE_Select_Reactor::register_handler_i (handle
,
192 #if !defined ACE_WIN32
193 if (ACE_BIT_ENABLED (mask
, ACE_Event_Handler::READ_MASK
))
194 ACE_SET_BITS (condition
, TK_READABLE
);
195 if (ACE_BIT_ENABLED (mask
, ACE_Event_Handler::WRITE_MASK
))
196 ACE_SET_BITS (condition
, TK_WRITABLE
);
197 if (ACE_BIT_ENABLED (mask
, ACE_Event_Handler::EXCEPT_MASK
))
198 ACE_SET_BITS (condition
, TK_EXCEPTION
);
199 if (ACE_BIT_ENABLED (mask
, ACE_Event_Handler::ACCEPT_MASK
))
200 ACE_SET_BITS (condition
, TK_READABLE
);
201 if (ACE_BIT_ENABLED (mask
, ACE_Event_Handler::CONNECT_MASK
)){
202 ACE_SET_BITS (condition
, TK_READABLE
); // connected, you may write
203 ACE_SET_BITS (condition
, TK_WRITABLE
); // connected, you have data/err
206 if (ACE_BIT_ENABLED (mask
, ACE_Event_Handler::READ_MASK
))
207 ACE_SET_BITS (condition
, TK_READABLE
);
208 if (ACE_BIT_ENABLED (mask
, ACE_Event_Handler::WRITE_MASK
))
209 ACE_SET_BITS (condition
, TK_WRITABLE
);
210 if (ACE_BIT_ENABLED (mask
, ACE_Event_Handler::EXCEPT_MASK
))
211 ACE_NOTSUP_RETURN(-1);
212 if (ACE_BIT_ENABLED (mask
, ACE_Event_Handler::ACCEPT_MASK
))
213 ACE_SET_BITS (condition
, TK_READABLE
);
214 if (ACE_BIT_ENABLED (mask
, ACE_Event_Handler::CONNECT_MASK
)){
215 ACE_SET_BITS (condition
, TK_READABLE
); // connected, you may write
216 ACE_SET_BITS (condition
, TK_WRITABLE
); // connected, you have data/err
218 #endif /* !ACE_WIN32 */
222 ACE_TkReactorID
*TkID
= this->ids_
;
226 if (TkID
->handle_
== handle
)
228 ::Tk_DeleteFileHandler (TkID
->handle_
);
230 ACE_TkReactor_Input_Callback
*callback
;
231 ACE_NEW_RETURN (callback
,
232 ACE_TkReactor_Input_Callback
,
234 callback
->reactor_
= this;
235 callback
->handle_
= handle
;
236 ::Tk_CreateFileHandler ((int) handle
,
239 (ClientData
) callback
);
246 ACE_NEW_RETURN (TkID
,
249 TkID
->next_
= this->ids_
;
250 TkID
->handle_
= handle
;
251 ACE_TkReactor_Input_Callback
*callback
;
252 ACE_NEW_RETURN (callback
,
253 ACE_TkReactor_Input_Callback
,
255 callback
->reactor_
= this;
256 callback
->handle_
= handle
;
258 ::Tk_CreateFileHandler ((int) handle
,
261 (ClientData
) callback
);
268 ACE_TkReactor::register_handler_i (const ACE_Handle_Set
&handles
,
269 ACE_Event_Handler
*handler
,
270 ACE_Reactor_Mask mask
)
272 return ACE_Select_Reactor::register_handler_i (handles
,
278 ACE_TkReactor::remove_handler_i (ACE_HANDLE handle
,
279 ACE_Reactor_Mask mask
)
281 ACE_TRACE ("ACE_TkReactor::remove_handler_i");
283 // In the registration phase we registered first with
284 // ACE_Select_Reactor and then with X. Now we are now doing things
287 // First clean up the corresponding X11Input.
288 this->remove_TkFileHandler (handle
);
290 // Now let the reactor do its work.
291 return ACE_Select_Reactor::remove_handler_i (handle
,
296 ACE_TkReactor::remove_TkFileHandler (ACE_HANDLE handle
)
298 ACE_TRACE ("ACE_TkReactor::remove_TkFileHandler");
300 ACE_TkReactorID
*TkID
= this->ids_
;
304 if (TkID
->handle_
== handle
)
306 ::Tk_DeleteFileHandler (TkID
->handle_
);
307 this->ids_
= TkID
->next_
;
312 ACE_TkReactorID
*NextID
= TkID
->next_
;
316 if (NextID
->handle_
== handle
)
318 ::Tk_DeleteFileHandler (NextID
->handle_
);
319 TkID
->next_
= NextID
->next_
;
326 NextID
= NextID
->next_
;
333 ACE_TkReactor::remove_handler_i (const ACE_Handle_Set
&handles
,
334 ACE_Reactor_Mask mask
)
336 return ACE_Select_Reactor::remove_handler_i (handles
,
340 // The following functions ensure that there is an Tk timeout for the
341 // first timeout in the Reactor's Timer_Queue.
344 ACE_TkReactor::reset_timeout ()
347 ::Tk_DeleteTimerHandler (this->timeout_
);
350 ACE_Time_Value
*max_wait_time
=
351 this->timer_queue_
->calculate_timeout (0);
354 timeout_
= ::Tk_CreateTimerHandler (max_wait_time
->msec (),
360 ACE_TkReactor::reset_timer_interval
362 const ACE_Time_Value
&interval
)
364 ACE_TRACE ("ACE_TkReactor::reset_timer_interval");
365 ACE_MT (ACE_GUARD_RETURN (ACE_Select_Reactor_Token
, ace_mon
, this->token_
, -1));
367 int result
= ACE_Select_Reactor::timer_queue_
->reset_interval
375 this->reset_timeout ();
381 ACE_TkReactor::schedule_timer (ACE_Event_Handler
*event_handler
,
383 const ACE_Time_Value
&delay
,
384 const ACE_Time_Value
&interval
)
386 ACE_TRACE ("ACE_TkReactor::schedule_timer");
387 ACE_MT (ACE_GUARD_RETURN (ACE_Select_Reactor_Token
, ace_mon
, this->token_
, -1));
389 long result
= ACE_Select_Reactor::schedule_timer (event_handler
,
397 this->reset_timeout ();
403 ACE_TkReactor::cancel_timer (ACE_Event_Handler
*handler
,
404 int dont_call_handle_close
)
406 ACE_TRACE ("ACE_TkReactor::cancel_timer");
408 if (ACE_Select_Reactor::cancel_timer (handler
,
409 dont_call_handle_close
) == -1)
413 this->reset_timeout ();
419 ACE_TkReactor::cancel_timer (long timer_id
,
421 int dont_call_handle_close
)
423 ACE_TRACE ("ACE_TkReactor::cancel_timer");
425 if (ACE_Select_Reactor::cancel_timer (timer_id
,
427 dont_call_handle_close
) == -1)
431 this->reset_timeout ();
436 ACE_END_VERSIONED_NAMESPACE_DECL