Merge pull request #2309 from mitza-oci/warnings
[ACE_TAO.git] / ACE / ace / TkReactor / TkReactor.cpp
blob3baaa71806150ffc9038a0482807bfc4364fbe62
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 ()
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);
68 } while (nfound == -1 && this->handle_error () > 0);
70 if (nfound > 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
81 void
82 ACE_TkReactor::TimerCallbackProc (ClientData cd)
84 ACE_TkReactor *self = (ACE_TkReactor *) cd;
85 self->timeout_ = 0;
87 // Deal with any timer events
88 ACE_Select_Reactor_Handle_Set handle_set;
89 self->dispatch (0, handle_set);
90 self->reset_timeout ();
93 /**
94 * @todo the unused mask argument is probably quite useful, but we
95 * ignore it, why? In fact the following comment probably
96 * relates to that:
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.
101 void
102 ACE_TkReactor::InputCallbackProc (ClientData cd,
103 int /* mask */)
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,
125 wait_set.rd_mask_,
126 wait_set.wr_mask_,
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).
132 if (result > 0)
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,
148 ACE_Time_Value *)
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,
154 temp_set.rd_mask_,
155 temp_set.wr_mask_,
156 temp_set.ex_mask_,
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
170 // <select>.
171 return ACE_OS::select (width,
172 wait_set.rd_mask_,
173 wait_set.wr_mask_,
174 wait_set.ex_mask_,
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,
186 handler, mask);
187 if (result == -1)
188 return -1;
190 int condition = 0;
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
205 #else
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 */
220 if (condition != 0)
222 ACE_TkReactorID *TkID = this->ids_;
224 while(TkID)
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,
233 -1);
234 callback->reactor_ = this;
235 callback->handle_ = handle;
236 ::Tk_CreateFileHandler ((int) handle,
237 condition,
238 InputCallbackProc,
239 (ClientData) callback);
240 return 0;
242 else
243 TkID = TkID->next_;
246 ACE_NEW_RETURN (TkID,
247 ACE_TkReactorID,
248 -1);
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,
254 -1);
255 callback->reactor_ = this;
256 callback->handle_ = handle;
258 ::Tk_CreateFileHandler ((int) handle,
259 condition,
260 InputCallbackProc,
261 (ClientData) callback);
262 this->ids_ = TkID;
264 return 0;
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,
273 handler,
274 mask);
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
285 // in reverse order.
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,
292 mask);
295 void
296 ACE_TkReactor::remove_TkFileHandler (ACE_HANDLE handle)
298 ACE_TRACE ("ACE_TkReactor::remove_TkFileHandler");
300 ACE_TkReactorID *TkID = this->ids_;
302 if (TkID)
304 if (TkID->handle_ == handle)
306 ::Tk_DeleteFileHandler (TkID->handle_);
307 this->ids_ = TkID->next_;
308 delete TkID;
309 return;
312 ACE_TkReactorID *NextID = TkID->next_;
314 while (NextID)
316 if (NextID->handle_ == handle)
318 ::Tk_DeleteFileHandler (NextID->handle_);
319 TkID->next_ = NextID->next_;
320 delete NextID;
321 return;
323 else
325 TkID = NextID;
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,
337 mask);
340 // The following functions ensure that there is an Tk timeout for the
341 // first timeout in the Reactor's Timer_Queue.
343 void
344 ACE_TkReactor::reset_timeout ()
346 if (this->timeout_)
347 ::Tk_DeleteTimerHandler (this->timeout_);
348 timeout_ = 0;
350 ACE_Time_Value *max_wait_time =
351 this->timer_queue_->calculate_timeout (0);
353 if (max_wait_time)
354 timeout_ = ::Tk_CreateTimerHandler (max_wait_time->msec (),
355 TimerCallbackProc,
356 (ClientData) this);
360 ACE_TkReactor::reset_timer_interval
361 (long timer_id,
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
368 (timer_id,
369 interval);
371 if (result == -1)
372 return -1;
373 else
375 this->reset_timeout ();
376 return result;
380 long
381 ACE_TkReactor::schedule_timer (ACE_Event_Handler *event_handler,
382 const void *arg,
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,
390 arg,
391 delay,
392 interval);
393 if (result == -1)
394 return -1;
395 else
397 this->reset_timeout ();
398 return result;
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)
410 return -1;
411 else
413 this->reset_timeout ();
414 return 0;
419 ACE_TkReactor::cancel_timer (long timer_id,
420 const void **arg,
421 int dont_call_handle_close)
423 ACE_TRACE ("ACE_TkReactor::cancel_timer");
425 if (ACE_Select_Reactor::cancel_timer (timer_id,
426 arg,
427 dont_call_handle_close) == -1)
428 return -1;
429 else
431 this->reset_timeout ();
432 return 0;
436 ACE_END_VERSIONED_NAMESPACE_DECL