XtReactor.cpp

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

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