Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

TkReactor.cpp

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

Generated on Mon Jun 16 11:21:54 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002