QtReactor.cpp

Go to the documentation of this file.
00001 //QtReactor.cpp,v 4.18 2006/04/19 19:13:09 jwillemsen Exp
00002 
00003 #include "ace/QtReactor.h"
00004 
00005 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00006 
00007 ACE_ALLOC_HOOK_DEFINE (ACE_QtReactor)
00008 
00009 // Must be called with lock held
00010 
00011 ACE_QtReactor::ACE_QtReactor (QApplication *qapp ,
00012     ACE_Sig_Handler *sh,
00013     ACE_Timer_Queue *tq,
00014     int disable_notify_pipe,
00015     ACE_Reactor_Notify *notify,
00016     int mask_signals,
00017     int s_queue ):
00018     ACE_Select_Reactor( sh, tq, disable_notify_pipe,
00019         notify, mask_signals, s_queue),
00020     qapp_(qapp),
00021     qtime_ (0)
00022 {
00023     reopen_notification_pipe();
00024 }
00025 
00026 // Must be called with lock held
00027 ACE_QtReactor::ACE_QtReactor (size_t size,
00028     QApplication *qapp,
00029     int restart,
00030     ACE_Sig_Handler *sh,
00031     ACE_Timer_Queue *tq,
00032     int disable_notify_pipe,
00033     ACE_Reactor_Notify *notify,
00034     int mask_signals,
00035     int s_queue):
00036     ACE_Select_Reactor( size, restart, sh, tq,
00037         disable_notify_pipe, notify, mask_signals,
00038         s_queue ),
00039     qapp_(qapp),
00040     qtime_ (0)
00041 
00042 {
00043     reopen_notification_pipe();
00044 }
00045 
00046 void ACE_QtReactor::reopen_notification_pipe( void)
00047 {
00048   // When the ACE_Select_Reactor is constructed it creates the notify
00049   // pipe and registers it with the register_handler_i() method. The
00050   // QtReactor overloads this method BUT because the
00051   // register_handler_i occurs when constructing the base class
00052   // ACE_Select_Reactor, the ACE_Select_Reactor register_handler_i()
00053   // is called not the QtReactor register_handler_i().  This means
00054   // that the notify pipe is registered with the ACE_Select_Reactor
00055   // event handling code not the QtReactor and so notfications don't
00056   // work.  To get around this we simply close and re-opened the
00057   // notification handler in the constructor of the QtReactor.
00058 
00059 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
00060     if ( initialized_ )
00061     {
00062         this->notify_handler_->close ();
00063 
00064         // Patch for MS Windows: close and open doesn't clear the read
00065         // fd_set, so reset it manually
00066         this->wait_set_.rd_mask_.reset ();
00067 
00068         this->notify_handler_->open (this, 0);
00069     }
00070 #endif /* ACE_MT_SAFE */
00071 }
00072 
00073 ACE_QtReactor::~ACE_QtReactor (void)
00074 {
00075     // iterate over QSocketNotifiers for read and release them
00076     MAP::ITERATOR iter = this->read_notifier_.begin ();
00077     MAP::ITERATOR iterEnd = this->read_notifier_.end ();
00078     while( iter != iterEnd )
00079     {
00080         MAP::ENTRY &entry = *iter;
00081         // QOBject destructor notifies qapplication (hopefully) on delete
00082         delete entry.int_id_;
00083         ++iter;
00084     }
00085 
00086     // iterate over QSocketNotifiers for write and release them
00087     this->write_notifier_.begin ();
00088     this->write_notifier_.end ();
00089     while( iter != iterEnd )
00090     {
00091         MAP::ENTRY &entry = *iter;
00092         // QOBject destructor notifies qapplication (hopefully) on delete
00093         delete entry.int_id_;
00094         ++iter;
00095     }
00096 
00097     // iterate over QSocketNotifiers for exceptions and release them
00098     this->exception_notifier_.begin ();
00099     this->exception_notifier_.end ();
00100     while( iter != iterEnd )
00101     {
00102         MAP::ENTRY &entry = *iter;
00103         // QOBject destructor notifies qapplication (hopefully) on delete
00104         delete entry.int_id_;
00105         ++iter;
00106     }
00107 
00108     // QOBject destructor notifies qapplication (hopefully) on delete
00109     delete qtime_;
00110 }
00111 
00112 void
00113 ACE_QtReactor::qapplication (QApplication *qapp)
00114 {
00115   // reparent QSocketNotifiers and QTimer
00116   qapp_ = qapp ;
00117 }
00118 
00119 void
00120 ACE_QtReactor::timeout_event (void)
00121 {
00122   // Deal with any timer events
00123   ACE_Select_Reactor_Handle_Set handle_set;
00124   this->dispatch (0, handle_set );
00125 
00126   // Set next timeout signal
00127   this->reset_timeout ();
00128 }
00129 
00130 void
00131 ACE_QtReactor::read_event (int p_handle)
00132 {
00133   ACE_TRACE ("ACE_QtReactor::read_event");
00134 
00135   ACE_HANDLE handle = ACE_HANDLE( p_handle );
00136 
00137 #ifdef ACE_QTREACTOR_CLEAR_PENDING_EVENTS
00138   // disable socket notifier to clear pending events
00139   QSocketNotifier *qsock_notifier = 0;
00140   if ( ( this->read_notifier_.find( handle,
00141              qsock_notifier) != -1) )
00142     qsock_notifier->setEnabled( false );
00143 #endif /* ACE_QTREACTOR_CLEAR_PENDING_EVENTS  */
00144 
00145   // The core of read event handling
00146   ACE_Select_Reactor_Handle_Set dispatch_set;
00147 
00148   dispatch_set.rd_mask_.set_bit ( handle );
00149   this->dispatch (1, dispatch_set);
00150 
00151 #ifdef ACE_QTREACTOR_CLEAR_PENDING_EVENTS
00152   // enable socket notifier according to current mask
00153   ACE_Reactor_Mask mask = 0;
00154   mask = mask_ops( handle, mask, ACE_Reactor::GET_MASK );
00155   if ( -1 != mask )
00156         set_enable_flag_by_mask ( 1, handle, mask);
00157 #endif /* ACE_QTREACTOR_CLEAR_PENDING_EVENTS  */
00158 }
00159 
00160 void
00161 ACE_QtReactor::write_event (int p_handle)
00162 {
00163   ACE_TRACE ("ACE_QtReactor::write_event");
00164 
00165   ACE_HANDLE handle = ACE_HANDLE( p_handle );
00166 
00167 #ifdef ACE_QTREACTOR_CLEAR_PENDING_EVENTS
00168   // disable socket notifier to clear pending events
00169   QSocketNotifier *qsock_notifier = 0;
00170   if ( ( this->write_notifier_.find( handle, qsock_notifier) != -1) )
00171     qsock_notifier->setEnabled( false );
00172 #endif /* ACE_QTREACTOR_CLEAR_PENDING_EVENTS  */
00173 
00174   // The core of write event handling
00175   ACE_Select_Reactor_Handle_Set dispatch_set;
00176 
00177   dispatch_set.wr_mask_.set_bit( handle );
00178   this->dispatch (1, dispatch_set);
00179 
00180 #ifdef ACE_QTREACTOR_CLEAR_PENDING_EVENTS
00181   // enable socket notifier according to current mask
00182   ACE_Reactor_Mask mask = 0;
00183   mask = mask_ops( handle, mask, ACE_Reactor::GET_MASK );
00184   if ( -1 != mask )
00185         set_enable_flag_by_mask ( 1, handle, mask);
00186 #endif /* ACE_QTREACTOR_CLEAR_PENDING_EVENTS  */
00187 }
00188 
00189 void
00190 ACE_QtReactor::exception_event (int p_handle)
00191 {
00192   ACE_TRACE ("ACE_QtReactor::exception_event");
00193 
00194   ACE_HANDLE handle = ACE_HANDLE( p_handle );
00195 
00196 
00197 #ifdef ACE_QTREACTOR_CLEAR_PENDING_EVENTS
00198   // disable socket notifier to clear pending events
00199   QSocketNotifier *qsock_notifier = 0;
00200   if ( ( this->exception_notifier_.find( handle, qsock_notifier) != -1) )
00201     qsock_notifier->setEnabled( false );
00202 #endif /* ACE_QTREACTOR_CLEAR_PENDING_EVENTS  */
00203 
00204   // The core of exception event handling
00205   ACE_Select_Reactor_Handle_Set dispatch_set;
00206 
00207   dispatch_set.ex_mask_.set_bit( handle );
00208   dispatch (1, dispatch_set);
00209 
00210 #ifdef ACE_QTREACTOR_CLEAR_PENDING_EVENTS
00211   // enable socket notifier according to current mask
00212   ACE_Reactor_Mask mask = 0;
00213   mask = mask_ops( handle, mask, ACE_Reactor::GET_MASK );
00214   if ( -1 != mask )
00215         set_enable_flag_by_mask ( 1, handle, mask);
00216 #endif /* ACE_QTREACTOR_CLEAR_PENDING_EVENTS  */
00217 }
00218 
00219 int
00220 ACE_QtReactor::set_enable_flag_by_mask (int flag_value,
00221                                         ACE_HANDLE handle,
00222                                         ACE_Reactor_Mask mask)
00223 {
00224   QSocketNotifier *qs_not;
00225 
00226   if (ACE_BIT_ENABLED(mask, ACE_Event_Handler::READ_MASK) ||
00227       ACE_BIT_ENABLED( mask, ACE_Event_Handler::ACCEPT_MASK))
00228     {
00229       // Find the current notifier
00230       qs_not = 0;
00231       if ((this->read_notifier_.find (handle, qs_not) == -1))
00232         return -1;
00233 
00234       qs_not->setEnabled (flag_value);
00235     }
00236 
00237   if (ACE_BIT_ENABLED( mask, ACE_Event_Handler::WRITE_MASK) ||
00238       ACE_BIT_ENABLED( mask, ACE_Event_Handler::ACCEPT_MASK) ||
00239       ACE_BIT_ENABLED( mask, ACE_Event_Handler::CONNECT_MASK))
00240     {
00241       qs_not = 0;
00242       if ((this->write_notifier_.find (handle, qs_not) == -1))
00243         return -1;
00244 
00245       qs_not->setEnabled (flag_value);
00246     }
00247 
00248   if (ACE_BIT_ENABLED( mask,
00249                        ACE_Event_Handler::EXCEPT_MASK))
00250     {
00251       qs_not = 0;
00252       if ((this->exception_notifier_.find (handle, qs_not) == -1))
00253         return -1;
00254 
00255       qs_not->setEnabled (flag_value);
00256     }
00257 
00258   return 0;
00259 }
00260 
00261 int
00262 ACE_QtReactor::bit_ops (ACE_HANDLE handle,
00263                         ACE_Reactor_Mask mask,
00264                         ACE_Select_Reactor_Handle_Set &handle_set,
00265                         int ops)
00266 {
00267   int result;
00268   ACE_Select_Reactor_Handle_Set preserved_handle_set = handle_set;
00269 
00270   // Call regular bit_ops
00271   if ((result = ACE_Select_Reactor::bit_ops (handle, mask, handle_set, ops)) == -1)
00272     return -1;
00273 
00274   // disable or enable the notifiers based on handle_set and mask
00275   int enableFlag = -1;
00276   if (&handle_set == &this->suspend_set_)
00277     enableFlag = 0;
00278   else if (&handle_set == &this->wait_set_)
00279     enableFlag = 1;
00280   else
00281     // We have no work to do here, so just return
00282     return result;
00283 
00284   switch (ops)
00285     {
00286     case ACE_Reactor::SET_MASK:
00287     case ACE_Reactor::ADD_MASK:
00288       // Enable or disable notifiers based on the specified masks
00289       if (this->set_enable_flag_by_mask (enableFlag, handle, mask) == -1)
00290         {
00291           // We can't just return -1 here because we'll have half-changed things.
00292           // So, we need to restore the old handle_set, then return -1.
00293           handle_set = preserved_handle_set;
00294           return -1;
00295         }
00296       break;
00297 
00298     case ACE_Reactor::CLR_MASK:
00299       if (this->set_enable_flag_by_mask (!enableFlag, handle, mask) == -1)
00300         {
00301           handle_set = preserved_handle_set;
00302           return -1;
00303         }
00304       break;
00305 
00306     default:
00307       // we take no action for any other operations
00308       break;
00309     }
00310 
00311   return result;
00312 }
00313 
00314 void
00315 ACE_QtReactor::create_notifiers_for_handle (ACE_HANDLE handle)
00316 {
00317     QSocketNotifier *qsock_notifier = 0;
00318 
00319     // if there is already a read socket notifier for this handle, do nothing
00320     // otherwise create read notifier
00321     if ( ( this->read_notifier_.find (handle,
00322                qsock_notifier) == -1) )
00323     {
00324         ACE_NEW (qsock_notifier,
00325             QSocketNotifier (int(handle), QSocketNotifier::Read, this));
00326         this->read_notifier_.bind (handle,
00327             qsock_notifier);
00328         QObject::connect (qsock_notifier,
00329             SIGNAL (activated (int)),
00330             this,
00331             SLOT (read_event (int))) ;
00332         // disable; it will be enabled by the regular register_handler_i if
00333         // necessary
00334         qsock_notifier->setEnabled (0);
00335     }
00336 
00337     qsock_notifier = 0;
00338 
00339 
00340     // if there is already a write socket notifier for this handle, do nothing
00341     // otherwise create read notifier
00342     if ((this->write_notifier_.find (handle,
00343              qsock_notifier) == -1))
00344     {
00345         ACE_NEW (qsock_notifier,
00346             QSocketNotifier (int(handle), QSocketNotifier::Write, this));
00347 
00348         this->write_notifier_.bind (handle,
00349             qsock_notifier);
00350 
00351         QObject::connect (qsock_notifier,
00352             SIGNAL (activated (int)),
00353             this,
00354             SLOT (write_event (int)));
00355         // disable; it will be enabled by the regular register_handler_i if
00356         // necessary
00357         qsock_notifier->setEnabled (0);
00358     }
00359 
00360 
00361     qsock_notifier = 0;
00362 
00363     // if there is already a write socket notifier for this handle, do nothing
00364     // otherwise create read notifier
00365     if ((this->exception_notifier_.find (handle,
00366              qsock_notifier) == -1))
00367     {
00368 
00369         ACE_NEW (qsock_notifier,
00370             QSocketNotifier (int(handle), QSocketNotifier::Exception, this));
00371 
00372         this->exception_notifier_.bind (handle,
00373             qsock_notifier);
00374 
00375         QObject::connect (qsock_notifier,
00376             SIGNAL (activated (int)),
00377             this,
00378             SLOT (exception_event (int))) ;
00379         // disable; it will be enabled by the regular register_handler_i if
00380         // necessary
00381         qsock_notifier->setEnabled (0);
00382     }
00383 }
00384 
00385 void
00386 ACE_QtReactor::destroy_notifiers_for_handle (ACE_HANDLE handle)
00387 {
00388   QSocketNotifier *qsock_notifier = 0;
00389 
00390   // Looks for the handle in the maps and removes them.
00391 
00392   if ((this->read_notifier_.find (handle,
00393                                   qsock_notifier) != -1))
00394     {
00395       this->read_notifier_.unbind (handle,
00396                                    qsock_notifier);
00397       delete qsock_notifier;
00398     }
00399 
00400   if ((this->write_notifier_.find (handle,
00401                                    qsock_notifier) != -1))
00402     {
00403       this->write_notifier_.unbind (handle,
00404                                     qsock_notifier);
00405       delete qsock_notifier;
00406     }
00407 
00408 
00409   if ((this->exception_notifier_.find (handle,
00410                                        qsock_notifier) != -1))
00411     {
00412       this->exception_notifier_.unbind (handle,
00413                                         qsock_notifier);
00414       delete qsock_notifier;
00415     }
00416 }
00417 
00418 int
00419 ACE_QtReactor::register_handler_i (ACE_HANDLE handle ,
00420                                    ACE_Event_Handler *handler,
00421                                    ACE_Reactor_Mask mask)
00422 {
00423   ACE_TRACE ("ACE_QtReactor::register_handler_i");
00424 
00425   this->create_notifiers_for_handle (handle);
00426 
00427   int result;
00428   if ((result = ACE_Select_Reactor::register_handler_i(handle,
00429                                                        handler,
00430                                                        mask ))
00431       == -1)
00432     {
00433         // destroy notifiers only when there is no handler for handle
00434         if ( !ACE_Select_Reactor::find_handler( handle ) )
00435             this->destroy_notifiers_for_handle (handle);
00436       return -1;
00437     }
00438 
00439   return 0;
00440 }
00441 
00442 int
00443 ACE_QtReactor::register_handler_i (const ACE_Handle_Set &handles,
00444                                    ACE_Event_Handler *handler,
00445                                    ACE_Reactor_Mask mask)
00446 {
00447   return ACE_Select_Reactor::register_handler_i(handles,
00448                                                 handler,
00449                                                 mask);
00450 }
00451 
00452 int ACE_QtReactor::remove_handler_i (ACE_HANDLE handle ,
00453                                      ACE_Reactor_Mask mask   )
00454 {
00455   ACE_TRACE ("ACE_QtReactor::remove_handler_i");
00456 
00457   int result = ACE_Select_Reactor::remove_handler_i (handle, mask);
00458   // destroy notifiers only when there is no handler for handle
00459   if ( !ACE_Select_Reactor::find_handler( handle ) )
00460       this->destroy_notifiers_for_handle (handle);
00461   return result;
00462 }
00463 
00464 
00465 int
00466 ACE_QtReactor::remove_handler_i (const ACE_Handle_Set &handles,
00467                                  ACE_Reactor_Mask  mask)
00468 {
00469   return ACE_Select_Reactor::remove_handler_i (handles,
00470                                                mask);
00471 }
00472 
00473 // The following functions ensure that there is an Qt timeout for the
00474 // first timeout in the Reactor's Timer_Queue.
00475 
00476 void
00477 ACE_QtReactor::reset_timeout (void)
00478 {
00479   if (this->qtime_ != 0)
00480     {
00481       delete this->qtime_;
00482       this->qtime_ = 0;
00483     }
00484 
00485   ACE_Time_Value *max_wait_time =
00486     this->timer_queue_->calculate_timeout (0) ;
00487 
00488   if (max_wait_time)
00489   {
00490     ACE_NEW (this->qtime_,
00491              QTimer);
00492 
00493     QObject::connect (qtime_,
00494                       SIGNAL (timeout ()),
00495                       this,
00496                       SLOT (timeout_event ()));
00497 
00498     qtime_->start(max_wait_time->msec(), 1);
00499   }
00500 
00501 }
00502 
00503 
00504 long
00505 ACE_QtReactor::schedule_timer (ACE_Event_Handler *handler,
00506                                const void *arg,
00507                                const ACE_Time_Value &delay_time,
00508                                const ACE_Time_Value &interval)
00509 {
00510   ACE_TRACE ("ACE_QtReactor::schedule_timer");
00511   ACE_MT (ACE_GUARD_RETURN (ACE_Select_Reactor_Token,
00512                             ace_mon,
00513                             this->token_,
00514                             -1));
00515 
00516   long result;
00517   if ((result = ACE_Select_Reactor::schedule_timer(handler,
00518                                                    arg,
00519                                                    delay_time,
00520                                                    interval)) == -1 )
00521     return -1;
00522   else
00523   {
00524     this->reset_timeout ();
00525     return result;
00526   }
00527 }
00528 
00529 int
00530 ACE_QtReactor::cancel_timer (ACE_Event_Handler *handler,
00531                              int dont_call_handle_close)
00532 {
00533   ACE_TRACE ("ACE_QtReactor::cancel_timer");
00534 
00535   if (ACE_Select_Reactor::cancel_timer (handler,
00536                                         dont_call_handle_close ) == -1 )
00537     return -1 ;
00538   else
00539   {
00540     this->reset_timeout( ) ;
00541     return 0 ;
00542   }
00543 }
00544 
00545 int ACE_QtReactor::cancel_timer (long  timer_id,
00546                                  const void **arg,
00547                                  int dont_call_handle_close )
00548 {
00549   ACE_TRACE ("ACE_QtReactor::cancel_timer") ;
00550 
00551   if (ACE_Select_Reactor::cancel_timer (timer_id,
00552                                         arg,
00553                                         dont_call_handle_close ) == -1 )
00554     return -1 ;
00555   else
00556   {
00557     this->reset_timeout( ) ;
00558     return 0 ;
00559   }
00560 }
00561 
00562 // mbrudka: who needs QtWaitForMultipleEvents? It seems it's cargo load now!
00563 int
00564 ACE_QtReactor::QtWaitForMultipleEvents (int width,
00565                                         ACE_Select_Reactor_Handle_Set &wait_set,
00566                                         ACE_Time_Value * /*max_wait_time*/)
00567 {
00568   // Check to make sure our handle's are all usable.
00569   ACE_Select_Reactor_Handle_Set temp_set = wait_set;
00570 
00571   if (ACE_OS::select (width,
00572                       temp_set.rd_mask_,
00573                       temp_set.wr_mask_,
00574                       temp_set.ex_mask_,
00575                       (ACE_Time_Value *) &ACE_Time_Value::zero ) == -1)
00576     return -1; // Bad file arguments...
00577 
00578   // Qt processing.
00579   this->qapp_->processOneEvent ();
00580 
00581   // Reset the width, in case it changed during the upcalls.
00582   width = handler_rep_.max_handlep1 ();
00583 
00584   // Now actually read the result needed by the <Select_Reactor> using
00585   // <select>.
00586   return ACE_OS::select(width,
00587                         wait_set.rd_mask_,
00588                         wait_set.wr_mask_,
00589                         wait_set.ex_mask_,
00590                         (ACE_Time_Value *) &ACE_Time_Value::zero);
00591 }
00592 
00593 // mbrudka: who needs wait_for_multiple_events? It seems it's cargo load now!
00594 int
00595 ACE_QtReactor::wait_for_multiple_events (
00596   ACE_Select_Reactor_Handle_Set &handle_set,
00597   ACE_Time_Value *max_wait_time)
00598 {
00599   ACE_TRACE ("ACE_QtReactor::wait_for_multiple_events");
00600 
00601   int nfound = 0;
00602   do
00603   {
00604     max_wait_time = this->timer_queue_->calculate_timeout (max_wait_time);
00605     size_t width = this->handler_rep_.max_handlep1 ();
00606     handle_set.rd_mask_ = this->wait_set_.rd_mask_;
00607     handle_set.wr_mask_ = this->wait_set_.wr_mask_;
00608     handle_set.ex_mask_ = this->wait_set_.ex_mask_;
00609 
00610     nfound = QtWaitForMultipleEvents (width,
00611                                       handle_set,
00612                                       max_wait_time);
00613 
00614   } while( nfound == -1 && this->handle_error () > 0 );
00615 
00616   if (nfound > 0)
00617   {
00618 #if !defined (ACE_WIN32)
00619     handle_set.rd_mask_.sync (this->handler_rep_.max_handlep1 ());
00620     handle_set.wr_mask_.sync (this->handler_rep_.max_handlep1 ());
00621     handle_set.ex_mask_.sync (this->handler_rep_.max_handlep1 ());
00622 #endif /* ACE_WIN32 */
00623   }
00624 
00625   return nfound;
00626   // Timed out or input available
00627 }
00628 
00629 ACE_END_VERSIONED_NAMESPACE_DECL

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