TkReactor.cpp

Go to the documentation of this file.
00001 #include "ace/TkReactor.h"
00002 
00003 #include "ace/SOCK_Acceptor.h"
00004 #include "ace/SOCK_Connector.h"
00005 
00006 ACE_RCSID(ace, TkReactor, "TkReactor.cpp,v 4.15 2005/10/28 23:55:10 ossama Exp")
00007 
00008 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00009 
00010 ACE_ALLOC_HOOK_DEFINE (ACE_TkReactor)
00011 
00012 // Must be called with lock held
00013 ACE_TkReactor::ACE_TkReactor (size_t size,
00014                               int restart,
00015                               ACE_Sig_Handler *h)
00016   : ACE_Select_Reactor (size, restart, h),
00017     ids_ (0),
00018     timeout_ (0)
00019 {
00020   // When the ACE_Select_Reactor is constructed it creates the notify
00021   // pipe and registers it with the register_handler_i() method. The
00022   // TkReactor overloads this method BUT because the
00023   // register_handler_i occurs when constructing the base class
00024   // ACE_Select_Reactor, the ACE_Select_Reactor register_handler_i()
00025   // is called not the TkReactor register_handler_i().  This means
00026   // that the notify pipe is registered with the ACE_Select_Reactor
00027   // event handling code not the TkReactor and so notfications don't
00028   // work.  To get around this we simply close and re-opened the
00029   // notification handler in the constructor of the TkReactor.
00030 
00031 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
00032   this->notify_handler_->close ();
00033   this->notify_handler_->open (this, 0);
00034 #endif /* ACE_MT_SAFE */
00035 }
00036 
00037 ACE_TkReactor::~ACE_TkReactor (void)
00038 {
00039   // Delete the remaining items in the linked list.
00040 
00041   while (this->ids_)
00042     {
00043       ACE_TkReactorID *TkID = this->ids_->next_;
00044       delete this->ids_;
00045       this->ids_ = TkID;
00046     }
00047 }
00048 
00049 // This is just the <wait_for_multiple_events> from ace/Reactor.cpp
00050 // but we use the Tk functions to wait for an event, not <select>
00051 
00052 int
00053 ACE_TkReactor::wait_for_multiple_events (ACE_Select_Reactor_Handle_Set &handle_set,
00054                                          ACE_Time_Value *max_wait_time)
00055 {
00056   ACE_TRACE ("ACE_TkReactor::wait_for_multiple_events");
00057   int nfound;
00058 
00059   do
00060     {
00061       max_wait_time = this->timer_queue_->calculate_timeout (max_wait_time);
00062 
00063       size_t width = this->handler_rep_.max_handlep1 ();
00064       handle_set.rd_mask_ = this->wait_set_.rd_mask_;
00065       handle_set.wr_mask_ = this->wait_set_.wr_mask_;
00066       handle_set.ex_mask_ = this->wait_set_.ex_mask_;
00067       nfound = TkWaitForMultipleEvents (width,
00068                                         handle_set,
00069                                         max_wait_time);
00070 
00071     } while (nfound == -1 && this->handle_error () > 0);
00072 
00073   if (nfound > 0)
00074     {
00075 #if !defined (ACE_WIN32)
00076       handle_set.rd_mask_.sync (this->handler_rep_.max_handlep1 ());
00077       handle_set.wr_mask_.sync (this->handler_rep_.max_handlep1 ());
00078       handle_set.ex_mask_.sync (this->handler_rep_.max_handlep1 ());
00079 #endif /* ACE_WIN32 */
00080     }
00081   return nfound; // Timed out or input available
00082 }
00083 
00084 void
00085 ACE_TkReactor::TimerCallbackProc (ClientData cd)
00086 {
00087   ACE_TkReactor *self = (ACE_TkReactor *) cd;
00088   self->timeout_ = 0;
00089 
00090   // Deal with any timer events
00091   ACE_Select_Reactor_Handle_Set handle_set;
00092   self->dispatch (0, handle_set);
00093   self->reset_timeout ();
00094 }
00095 
00096 /**
00097  * @todo the unused mask argument is probably quite useful, but we
00098  *       ignore it, why?  In fact the following comment probably
00099  *       relates to that:
00100  *       This could be made shorter if we know which *kind* of event
00101  *       we were about to get.  Here we use <select> to find out which
00102  *       one might be available.
00103  */
00104 void
00105 ACE_TkReactor::InputCallbackProc (ClientData cd,
00106                                   int /* mask */)
00107 {
00108   ACE_TkReactor_Input_Callback *callback = (ACE_TkReactor_Input_Callback *) cd;
00109   ACE_TkReactor *self = callback->reactor_;
00110   ACE_HANDLE handle = callback->handle_;
00111 
00112   // my copy isn't const.
00113   ACE_Time_Value zero = ACE_Time_Value::zero;
00114 
00115   ACE_Select_Reactor_Handle_Set wait_set;
00116 
00117   // Deal with one file event.
00118 
00119   // - read which kind of event
00120   if (self->wait_set_.rd_mask_.is_set (handle))
00121     wait_set.rd_mask_.set_bit (handle);
00122   if (self->wait_set_.wr_mask_.is_set (handle))
00123     wait_set.wr_mask_.set_bit (handle);
00124   if (self->wait_set_.ex_mask_.is_set (handle))
00125     wait_set.ex_mask_.set_bit (handle);
00126 
00127   int result = ACE_OS::select (handle + 1,
00128                                wait_set.rd_mask_,
00129                                wait_set.wr_mask_,
00130                                wait_set.ex_mask_, &zero);
00131 
00132   ACE_Select_Reactor_Handle_Set dispatch_set;
00133 
00134   // - Use only that one file event (removes events for other files).
00135   if (result > 0)
00136     {
00137       if (wait_set.rd_mask_.is_set (handle))
00138         dispatch_set.rd_mask_.set_bit (handle);
00139       if (wait_set.wr_mask_.is_set (handle))
00140         dispatch_set.wr_mask_.set_bit (handle);
00141       if (wait_set.ex_mask_.is_set (handle))
00142         dispatch_set.ex_mask_.set_bit (handle);
00143 
00144       self->dispatch (1, dispatch_set);
00145     }
00146 }
00147 
00148 int
00149 ACE_TkReactor::TkWaitForMultipleEvents (int width,
00150                                         ACE_Select_Reactor_Handle_Set &wait_set,
00151                                         ACE_Time_Value *)
00152 {
00153   // Check to make sure our handle's are all usable.
00154   ACE_Select_Reactor_Handle_Set temp_set = wait_set;
00155 
00156   if (ACE_OS::select (width,
00157                       temp_set.rd_mask_,
00158                       temp_set.wr_mask_,
00159                       temp_set.ex_mask_,
00160                       (ACE_Time_Value *) &ACE_Time_Value::zero) == -1)
00161     return -1; // Bad file arguments...
00162 
00163   // Instead of waiting using <select>, just use the Tk mechanism to
00164   // wait for a single event.
00165 
00166   // Wait for something to happen.
00167   ::Tcl_DoOneEvent (0);
00168 
00169   // Reset the width, in case it changed during the upcalls.
00170   width = this->handler_rep_.max_handlep1 ();
00171 
00172   // Now actually read the result needed by the <Select_Reactor> using
00173   // <select>.
00174   return ACE_OS::select (width,
00175                          wait_set.rd_mask_,
00176                          wait_set.wr_mask_,
00177                          wait_set.ex_mask_,
00178                          (ACE_Time_Value *) &ACE_Time_Value::zero);
00179 }
00180 
00181 int
00182 ACE_TkReactor::register_handler_i (ACE_HANDLE handle,
00183                                    ACE_Event_Handler *handler,
00184                                    ACE_Reactor_Mask mask)
00185 {
00186   ACE_TRACE ("ACE_TkReactor::register_handler_i");
00187 
00188   int result = ACE_Select_Reactor::register_handler_i (handle,
00189                                                        handler, mask);
00190   if (result == -1)
00191     return -1;
00192 
00193   int condition = 0;
00194 
00195 #if !defined ACE_WIN32
00196   if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::READ_MASK))
00197     ACE_SET_BITS (condition, TK_READABLE);
00198   if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::WRITE_MASK))
00199     ACE_SET_BITS (condition, TK_WRITABLE);
00200   if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::EXCEPT_MASK))
00201     ACE_SET_BITS (condition, TK_EXCEPTION);
00202   if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::ACCEPT_MASK))
00203     ACE_SET_BITS (condition, TK_READABLE);
00204   if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::CONNECT_MASK)){
00205       ACE_SET_BITS (condition, TK_READABLE); // connected, you may write
00206       ACE_SET_BITS (condition, TK_WRITABLE);  // connected, you have data/err
00207   }
00208 #else
00209   if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::READ_MASK))
00210     ACE_SET_BITS (condition, TK_READABLE);
00211   if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::WRITE_MASK))
00212     ACE_SET_BITS (condition, TK_WRITABLE);
00213   if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::EXCEPT_MASK))
00214     ACE_NOTSUP_RETURN(-1);
00215   if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::ACCEPT_MASK))
00216     ACE_SET_BITS (condition, TK_READABLE);
00217   if (ACE_BIT_ENABLED (mask, ACE_Event_Handler::CONNECT_MASK)){
00218       ACE_SET_BITS (condition, TK_READABLE); // connected, you may write
00219       ACE_SET_BITS (condition, TK_WRITABLE);  // connected, you have data/err
00220   }
00221 #endif /* !ACE_WIN32 */
00222 
00223   if (condition != 0)
00224     {
00225       ACE_TkReactorID *TkID = this->ids_;
00226 
00227       while(TkID)
00228         {
00229           if (TkID->handle_ == handle)
00230             {
00231               ::Tk_DeleteFileHandler (TkID->handle_);
00232 
00233               ACE_TkReactor_Input_Callback *callback;
00234               ACE_NEW_RETURN (callback,
00235                               ACE_TkReactor_Input_Callback,
00236                               -1);
00237               callback->reactor_ = this;
00238               callback->handle_ = handle;
00239               ::Tk_CreateFileHandler ((int) handle,
00240                                       condition,
00241                                       InputCallbackProc,
00242                                       (ClientData) callback);
00243               return 0;
00244             }
00245           else
00246             TkID = TkID->next_;
00247         }
00248 
00249       ACE_NEW_RETURN (TkID,
00250                       ACE_TkReactorID,
00251                       -1);
00252       TkID->next_ = this->ids_;
00253       TkID->handle_ = handle;
00254       ACE_TkReactor_Input_Callback *callback;
00255       ACE_NEW_RETURN (callback,
00256                       ACE_TkReactor_Input_Callback,
00257                       -1);
00258       callback->reactor_ = this;
00259       callback->handle_ = handle;
00260 
00261       ::Tk_CreateFileHandler ((int) handle,
00262                               condition,
00263                               InputCallbackProc,
00264                               (ClientData) callback);
00265       this->ids_ = TkID;
00266     }
00267   return 0;
00268 }
00269 
00270 int
00271 ACE_TkReactor::register_handler_i (const ACE_Handle_Set &handles,
00272                                    ACE_Event_Handler *handler,
00273                                    ACE_Reactor_Mask mask)
00274 {
00275   return ACE_Select_Reactor::register_handler_i (handles,
00276                                                  handler,
00277                                                  mask);
00278 }
00279 
00280 int
00281 ACE_TkReactor::remove_handler_i (ACE_HANDLE handle,
00282                                  ACE_Reactor_Mask mask)
00283 {
00284   ACE_TRACE ("ACE_TkReactor::remove_handler_i");
00285 
00286   // In the registration phase we registered first with
00287   // ACE_Select_Reactor and then with X.  Now we are now doing things
00288   // in reverse order.
00289 
00290   // First clean up the corresponding X11Input.
00291   this->remove_TkFileHandler (handle);
00292 
00293   // Now let the reactor do its work.
00294   return ACE_Select_Reactor::remove_handler_i (handle,
00295                                                mask);
00296 }
00297 
00298 void
00299 ACE_TkReactor::remove_TkFileHandler (ACE_HANDLE handle)
00300 {
00301   ACE_TRACE ("ACE_TkReactor::remove_TkFileHandler");
00302 
00303   ACE_TkReactorID *TkID = this->ids_;
00304 
00305   if (TkID)
00306     {
00307       if (TkID->handle_ == handle)
00308         {
00309           ::Tk_DeleteFileHandler (TkID->handle_);
00310           this->ids_ = TkID->next_;
00311           delete TkID;
00312           return;
00313         }
00314 
00315       ACE_TkReactorID *NextID = TkID->next_;
00316 
00317       while (NextID)
00318         {
00319           if (NextID->handle_ == handle)
00320             {
00321               ::Tk_DeleteFileHandler (NextID->handle_);
00322               TkID->next_ = NextID->next_;
00323               delete NextID;
00324               return;
00325             }
00326           else
00327             {
00328               TkID = NextID;
00329               NextID = NextID->next_;
00330             }
00331         }
00332     }
00333 }
00334 
00335 int
00336 ACE_TkReactor::remove_handler_i (const ACE_Handle_Set &handles,
00337                                  ACE_Reactor_Mask mask)
00338 {
00339   return ACE_Select_Reactor::remove_handler_i (handles,
00340                                                mask);
00341 }
00342 
00343 // The following functions ensure that there is an Tk timeout for the
00344 // first timeout in the Reactor's Timer_Queue.
00345 
00346 void
00347 ACE_TkReactor::reset_timeout (void)
00348 {
00349   if (this->timeout_)
00350     ::Tk_DeleteTimerHandler (this->timeout_);
00351   timeout_ = 0;
00352 
00353   ACE_Time_Value *max_wait_time =
00354     this->timer_queue_->calculate_timeout (0);
00355 
00356   if (max_wait_time)
00357     timeout_ = ::Tk_CreateTimerHandler (max_wait_time->msec (),
00358                                         TimerCallbackProc,
00359                                         (ClientData) this);
00360 }
00361 
00362 int
00363 ACE_TkReactor::reset_timer_interval
00364   (long timer_id,
00365    const ACE_Time_Value &interval)
00366 {
00367   ACE_TRACE ("ACE_TkReactor::reset_timer_interval");
00368   ACE_MT (ACE_GUARD_RETURN (ACE_Select_Reactor_Token, ace_mon, this->token_, -1));
00369 
00370   int result = ACE_Select_Reactor::timer_queue_->reset_interval
00371     (timer_id,
00372      interval);
00373 
00374   if (result == -1)
00375     return -1;
00376   else
00377     {
00378       this->reset_timeout ();
00379       return result;
00380     }
00381 }
00382 
00383 long
00384 ACE_TkReactor::schedule_timer (ACE_Event_Handler *event_handler,
00385                                const void *arg,
00386                 const ACE_Time_Value &delay,
00387                                const ACE_Time_Value &interval)
00388 {
00389   ACE_TRACE ("ACE_TkReactor::schedule_timer");
00390   ACE_MT (ACE_GUARD_RETURN (ACE_Select_Reactor_Token, ace_mon, this->token_, -1));
00391 
00392   long result = ACE_Select_Reactor::schedule_timer (event_handler,
00393                                                     arg,
00394                                                     delay,
00395                                                     interval);
00396   if (result == -1)
00397     return -1;
00398   else
00399     {
00400       this->reset_timeout ();
00401       return result;
00402     }
00403 }
00404 
00405 int
00406 ACE_TkReactor::cancel_timer (ACE_Event_Handler *handler,
00407                              int dont_call_handle_close)
00408 {
00409   ACE_TRACE ("ACE_TkReactor::cancel_timer");
00410 
00411   if (ACE_Select_Reactor::cancel_timer (handler,
00412                                         dont_call_handle_close) == -1)
00413     return -1;
00414   else
00415     {
00416       this->reset_timeout ();
00417       return 0;
00418     }
00419 }
00420 
00421 int
00422 ACE_TkReactor::cancel_timer (long timer_id,
00423                              const void **arg,
00424                              int dont_call_handle_close)
00425 {
00426   ACE_TRACE ("ACE_TkReactor::cancel_timer");
00427 
00428   if (ACE_Select_Reactor::cancel_timer (timer_id,
00429                                         arg,
00430                                         dont_call_handle_close) == -1)
00431     return -1;
00432   else
00433     {
00434       this->reset_timeout ();
00435       return 0;
00436     }
00437 }
00438 
00439 ACE_END_VERSIONED_NAMESPACE_DECL

Generated on Thu Nov 9 09:42:07 2006 for ACE by doxygen 1.3.6