Also use Objects as part of an operation but as a result don't generate Any operation...
[ACE_TAO.git] / ACE / ace / TkReactor / TkReactor.cpp
blob13c5904ccda2450ebc5860039f3e83e3a374acdb
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,
12 bool restart,
13 ACE_Sig_Handler *h)
14 : ACE_Select_Reactor (size, restart, h),
15 ids_ (0),
16 timeout_ (0)
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.
39 while (this->ids_)
41 ACE_TkReactorID *TkID = this->ids_->next_;
42 delete this->ids_;
43 this->ids_ = TkID;
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>
50 int
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");
55 int nfound;
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,
66 handle_set,
67 max_wait_time);
69 } while (nfound == -1 && this->handle_error () > 0);
71 if (nfound > 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
82 void
83 ACE_TkReactor::TimerCallbackProc (ClientData cd)
85 ACE_TkReactor *self = (ACE_TkReactor *) cd;
86 self->timeout_ = 0;
88 // Deal with any timer events
89 ACE_Select_Reactor_Handle_Set handle_set;
90 self->dispatch (0, handle_set);
91 self->reset_timeout ();
94 /**
95 * @todo the unused mask argument is probably quite useful, but we
96 * ignore it, why? In fact the following comment probably
97 * relates to that:
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.
102 void
103 ACE_TkReactor::InputCallbackProc (ClientData cd,
104 int /* mask */)
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,
126 wait_set.rd_mask_,
127 wait_set.wr_mask_,
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).
133 if (result > 0)
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,
149 ACE_Time_Value *)
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 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
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);
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,
187 handler, mask);
188 if (result == -1)
189 return -1;
191 int condition = 0;
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
206 #else
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 */
221 if (condition != 0)
223 ACE_TkReactorID *TkID = this->ids_;
225 while(TkID)
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,
234 -1);
235 callback->reactor_ = this;
236 callback->handle_ = handle;
237 ::Tk_CreateFileHandler ((int) handle,
238 condition,
239 InputCallbackProc,
240 (ClientData) callback);
241 return 0;
243 else
244 TkID = TkID->next_;
247 ACE_NEW_RETURN (TkID,
248 ACE_TkReactorID,
249 -1);
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,
255 -1);
256 callback->reactor_ = this;
257 callback->handle_ = handle;
259 ::Tk_CreateFileHandler ((int) handle,
260 condition,
261 InputCallbackProc,
262 (ClientData) callback);
263 this->ids_ = TkID;
265 return 0;
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,
274 handler,
275 mask);
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
286 // in reverse order.
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,
293 mask);
296 void
297 ACE_TkReactor::remove_TkFileHandler (ACE_HANDLE handle)
299 ACE_TRACE ("ACE_TkReactor::remove_TkFileHandler");
301 ACE_TkReactorID *TkID = this->ids_;
303 if (TkID)
305 if (TkID->handle_ == handle)
307 ::Tk_DeleteFileHandler (TkID->handle_);
308 this->ids_ = TkID->next_;
309 delete TkID;
310 return;
313 ACE_TkReactorID *NextID = TkID->next_;
315 while (NextID)
317 if (NextID->handle_ == handle)
319 ::Tk_DeleteFileHandler (NextID->handle_);
320 TkID->next_ = NextID->next_;
321 delete NextID;
322 return;
324 else
326 TkID = NextID;
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,
338 mask);
341 // The following functions ensure that there is an Tk timeout for the
342 // first timeout in the Reactor's Timer_Queue.
344 void
345 ACE_TkReactor::reset_timeout (void)
347 if (this->timeout_)
348 ::Tk_DeleteTimerHandler (this->timeout_);
349 timeout_ = 0;
351 ACE_Time_Value *max_wait_time =
352 this->timer_queue_->calculate_timeout (0);
354 if (max_wait_time)
355 timeout_ = ::Tk_CreateTimerHandler (max_wait_time->msec (),
356 TimerCallbackProc,
357 (ClientData) this);
361 ACE_TkReactor::reset_timer_interval
362 (long timer_id,
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
369 (timer_id,
370 interval);
372 if (result == -1)
373 return -1;
374 else
376 this->reset_timeout ();
377 return result;
381 long
382 ACE_TkReactor::schedule_timer (ACE_Event_Handler *event_handler,
383 const void *arg,
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,
391 arg,
392 delay,
393 interval);
394 if (result == -1)
395 return -1;
396 else
398 this->reset_timeout ();
399 return result;
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)
411 return -1;
412 else
414 this->reset_timeout ();
415 return 0;
420 ACE_TkReactor::cancel_timer (long timer_id,
421 const void **arg,
422 int dont_call_handle_close)
424 ACE_TRACE ("ACE_TkReactor::cancel_timer");
426 if (ACE_Select_Reactor::cancel_timer (timer_id,
427 arg,
428 dont_call_handle_close) == -1)
429 return -1;
430 else
432 this->reset_timeout ();
433 return 0;
437 ACE_END_VERSIONED_NAMESPACE_DECL