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

XtReactor.cpp

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

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