1 #include "ace/QtReactor/QtReactor.h"
3 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
5 ACE_ALLOC_HOOK_DEFINE (ACE_QtReactor
)
7 // Must be called with lock held
8 ACE_QtReactor::ACE_QtReactor (QApplication
*qapp
,
11 int disable_notify_pipe
,
12 ACE_Reactor_Notify
*notify
,
15 ACE_Select_Reactor( sh
, tq
, disable_notify_pipe
,
16 notify
, mask_signals
, s_queue
),
20 reopen_notification_pipe();
23 // Must be called with lock held
24 ACE_QtReactor::ACE_QtReactor (size_t size
,
29 int disable_notify_pipe
,
30 ACE_Reactor_Notify
*notify
,
33 ACE_Select_Reactor( size
, restart
, sh
, tq
,
34 disable_notify_pipe
, notify
, mask_signals
,
40 reopen_notification_pipe();
43 void ACE_QtReactor::reopen_notification_pipe()
45 // When the ACE_Select_Reactor is constructed it creates the notify
46 // pipe and registers it with the register_handler_i() method. The
47 // QtReactor overloads this method BUT because the
48 // register_handler_i occurs when constructing the base class
49 // ACE_Select_Reactor, the ACE_Select_Reactor register_handler_i()
50 // is called not the QtReactor register_handler_i(). This means
51 // that the notify pipe is registered with the ACE_Select_Reactor
52 // event handling code not the QtReactor and so notfications don't
53 // work. To get around this we simply close and re-opened the
54 // notification handler in the constructor of the QtReactor.
56 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
59 this->notify_handler_
->close ();
61 // Patch for MS Windows: close and open doesn't clear the read
62 // fd_set, so reset it manually
63 this->wait_set_
.rd_mask_
.reset ();
65 this->notify_handler_
->open (this, 0);
67 #endif /* ACE_MT_SAFE */
70 ACE_QtReactor::~ACE_QtReactor ()
72 // iterate over QSocketNotifiers for read and release them
73 MAP::ITERATOR iter
= this->read_notifier_
.begin ();
74 MAP::ITERATOR iterEnd
= this->read_notifier_
.end ();
75 while( iter
!= iterEnd
)
77 MAP::ENTRY
&entry
= *iter
;
78 // QOBject destructor notifies qapplication (hopefully) on delete
83 // iterate over QSocketNotifiers for write and release them
84 this->write_notifier_
.begin ();
85 this->write_notifier_
.end ();
86 while( iter
!= iterEnd
)
88 MAP::ENTRY
&entry
= *iter
;
89 // QOBject destructor notifies qapplication (hopefully) on delete
94 // iterate over QSocketNotifiers for exceptions and release them
95 this->exception_notifier_
.begin ();
96 this->exception_notifier_
.end ();
97 while( iter
!= iterEnd
)
99 MAP::ENTRY
&entry
= *iter
;
100 // QOBject destructor notifies qapplication (hopefully) on delete
101 delete entry
.int_id_
;
105 // QOBject destructor notifies qapplication (hopefully) on delete
110 ACE_QtReactor::qapplication (QApplication
*qapp
)
112 // reparent QSocketNotifiers and QTimer
117 ACE_QtReactor::timeout_event ()
119 // Deal with any timer events
120 ACE_Select_Reactor_Handle_Set handle_set
;
121 this->dispatch (0, handle_set
);
123 // Set next timeout signal
124 this->reset_timeout ();
129 ACE_QtReactor::handle_from_sender () const
131 // The argument passed to the Qt slot method is ignored due to this bug:
132 // https://bugreports.qt.io/browse/QTBUG-70441
133 QSocketNotifier
*const notifier
= dynamic_cast<QSocketNotifier
*> (this->sender ());
134 return notifier
? ACE_HANDLE (notifier
->socket ()) : ACE_INVALID_HANDLE
;
139 ACE_QtReactor::read_event (ACE_QT_HANDLE_TYPE p_handle
)
141 ACE_TRACE ("ACE_QtReactor::read_event");
144 ACE_UNUSED_ARG (p_handle
);
145 ACE_HANDLE
const handle
= this->handle_from_sender ();
147 ACE_HANDLE handle
= ACE_HANDLE( p_handle
);
150 #ifdef ACE_QTREACTOR_CLEAR_PENDING_EVENTS
151 // disable socket notifier to clear pending events
152 QSocketNotifier
*qsock_notifier
= 0;
153 if ( ( this->read_notifier_
.find( handle
,
154 qsock_notifier
) != -1) )
155 qsock_notifier
->setEnabled( false );
156 #endif /* ACE_QTREACTOR_CLEAR_PENDING_EVENTS */
158 // The core of read event handling
159 ACE_Select_Reactor_Handle_Set dispatch_set
;
161 dispatch_set
.rd_mask_
.set_bit ( handle
);
162 this->dispatch (1, dispatch_set
);
164 #ifdef ACE_QTREACTOR_CLEAR_PENDING_EVENTS
165 // enable socket notifier according to current mask
166 ACE_Reactor_Mask mask
= 0;
167 mask
= mask_ops( handle
, mask
, ACE_Reactor::GET_MASK
);
169 set_enable_flag_by_mask ( 1, handle
, mask
);
170 #endif /* ACE_QTREACTOR_CLEAR_PENDING_EVENTS */
174 ACE_QtReactor::write_event (ACE_QT_HANDLE_TYPE p_handle
)
176 ACE_TRACE ("ACE_QtReactor::write_event");
179 ACE_UNUSED_ARG (p_handle
);
180 ACE_HANDLE
const handle
= this->handle_from_sender ();
182 ACE_HANDLE handle
= ACE_HANDLE( p_handle
);
185 #ifdef ACE_QTREACTOR_CLEAR_PENDING_EVENTS
186 // disable socket notifier to clear pending events
187 QSocketNotifier
*qsock_notifier
= 0;
188 if ( ( this->write_notifier_
.find( handle
, qsock_notifier
) != -1) )
189 qsock_notifier
->setEnabled( false );
190 #endif /* ACE_QTREACTOR_CLEAR_PENDING_EVENTS */
192 // The core of write event handling
193 ACE_Select_Reactor_Handle_Set dispatch_set
;
195 dispatch_set
.wr_mask_
.set_bit( handle
);
196 this->dispatch (1, dispatch_set
);
198 #ifdef ACE_QTREACTOR_CLEAR_PENDING_EVENTS
199 // enable socket notifier according to current mask
200 ACE_Reactor_Mask mask
= 0;
201 mask
= mask_ops( handle
, mask
, ACE_Reactor::GET_MASK
);
203 set_enable_flag_by_mask ( 1, handle
, mask
);
204 #endif /* ACE_QTREACTOR_CLEAR_PENDING_EVENTS */
208 ACE_QtReactor::exception_event (ACE_QT_HANDLE_TYPE p_handle
)
210 ACE_TRACE ("ACE_QtReactor::exception_event");
213 ACE_UNUSED_ARG (p_handle
);
214 ACE_HANDLE
const handle
= this->handle_from_sender ();
216 ACE_HANDLE handle
= ACE_HANDLE( p_handle
);
219 #ifdef ACE_QTREACTOR_CLEAR_PENDING_EVENTS
220 // disable socket notifier to clear pending events
221 QSocketNotifier
*qsock_notifier
= 0;
222 if ( ( this->exception_notifier_
.find( handle
, qsock_notifier
) != -1) )
223 qsock_notifier
->setEnabled( false );
224 #endif /* ACE_QTREACTOR_CLEAR_PENDING_EVENTS */
226 // The core of exception event handling
227 ACE_Select_Reactor_Handle_Set dispatch_set
;
229 dispatch_set
.ex_mask_
.set_bit( handle
);
230 dispatch (1, dispatch_set
);
232 #ifdef ACE_QTREACTOR_CLEAR_PENDING_EVENTS
233 // enable socket notifier according to current mask
234 ACE_Reactor_Mask mask
= 0;
235 mask
= mask_ops( handle
, mask
, ACE_Reactor::GET_MASK
);
237 set_enable_flag_by_mask ( 1, handle
, mask
);
238 #endif /* ACE_QTREACTOR_CLEAR_PENDING_EVENTS */
242 ACE_QtReactor::set_enable_flag_by_mask (int flag_value
,
244 ACE_Reactor_Mask mask
)
246 QSocketNotifier
*qs_not
;
248 if (ACE_BIT_ENABLED(mask
, ACE_Event_Handler::READ_MASK
) ||
249 ACE_BIT_ENABLED( mask
, ACE_Event_Handler::ACCEPT_MASK
))
251 // Find the current notifier
253 if ((this->read_notifier_
.find (handle
, qs_not
) == -1))
256 qs_not
->setEnabled (flag_value
);
259 if (ACE_BIT_ENABLED( mask
, ACE_Event_Handler::WRITE_MASK
) ||
260 ACE_BIT_ENABLED( mask
, ACE_Event_Handler::ACCEPT_MASK
) ||
261 ACE_BIT_ENABLED( mask
, ACE_Event_Handler::CONNECT_MASK
))
264 if ((this->write_notifier_
.find (handle
, qs_not
) == -1))
267 qs_not
->setEnabled (flag_value
);
270 if (ACE_BIT_ENABLED( mask
,
271 ACE_Event_Handler::EXCEPT_MASK
))
274 if ((this->exception_notifier_
.find (handle
, qs_not
) == -1))
277 qs_not
->setEnabled (flag_value
);
284 ACE_QtReactor::bit_ops (ACE_HANDLE handle
,
285 ACE_Reactor_Mask mask
,
286 ACE_Select_Reactor_Handle_Set
&handle_set
,
290 ACE_Select_Reactor_Handle_Set preserved_handle_set
= handle_set
;
292 // Call regular bit_ops
293 if ((result
= ACE_Select_Reactor::bit_ops (handle
, mask
, handle_set
, ops
)) == -1)
296 // disable or enable the notifiers based on handle_set and mask
298 if (&handle_set
== &this->suspend_set_
)
300 else if (&handle_set
== &this->wait_set_
)
303 // We have no work to do here, so just return
308 case ACE_Reactor::SET_MASK
:
309 case ACE_Reactor::ADD_MASK
:
310 // Enable or disable notifiers based on the specified masks
311 if (this->set_enable_flag_by_mask (enableFlag
, handle
, mask
) == -1)
313 // We can't just return -1 here because we'll have half-changed things.
314 // So, we need to restore the old handle_set, then return -1.
315 handle_set
= preserved_handle_set
;
320 case ACE_Reactor::CLR_MASK
:
321 if (this->set_enable_flag_by_mask (!enableFlag
, handle
, mask
) == -1)
323 handle_set
= preserved_handle_set
;
329 // we take no action for any other operations
337 ACE_QtReactor::create_notifiers_for_handle (ACE_HANDLE handle
)
339 QSocketNotifier
*qsock_notifier
= 0;
341 // if there is already a read socket notifier for this handle, do nothing
342 // otherwise create read notifier
343 if ( ( this->read_notifier_
.find (handle
,
344 qsock_notifier
) == -1) )
346 ACE_NEW (qsock_notifier
,
347 QSocketNotifier (ACE_QT_HANDLE_TYPE(handle
), QSocketNotifier::Read
, this));
348 this->read_notifier_
.bind (handle
,
352 QObject::connect (qsock_notifier
, &QSocketNotifier::activated
, this, &ACE_QtReactor::read_event
);
354 QObject::connect (qsock_notifier
,
355 SIGNAL (activated (ACE_QT_HANDLE_TYPE
)),
357 SLOT (read_event (ACE_QT_HANDLE_TYPE
))) ;
359 // disable; it will be enabled by the regular register_handler_i if
361 qsock_notifier
->setEnabled (0);
367 // if there is already a write socket notifier for this handle, do nothing
368 // otherwise create read notifier
369 if ((this->write_notifier_
.find (handle
,
370 qsock_notifier
) == -1))
372 ACE_NEW (qsock_notifier
,
373 QSocketNotifier (ACE_QT_HANDLE_TYPE(handle
), QSocketNotifier::Write
, this));
375 this->write_notifier_
.bind (handle
,
379 QObject::connect (qsock_notifier
, &QSocketNotifier::activated
, this, &ACE_QtReactor::write_event
);
381 QObject::connect (qsock_notifier
,
382 SIGNAL (activated (ACE_QT_HANDLE_TYPE
)),
384 SLOT (write_event (ACE_QT_HANDLE_TYPE
)));
386 // disable; it will be enabled by the regular register_handler_i if
388 qsock_notifier
->setEnabled (0);
394 // if there is already a write socket notifier for this handle, do nothing
395 // otherwise create read notifier
396 if ((this->exception_notifier_
.find (handle
,
397 qsock_notifier
) == -1))
399 ACE_NEW (qsock_notifier
,
400 QSocketNotifier (ACE_QT_HANDLE_TYPE(handle
), QSocketNotifier::Exception
, this));
402 this->exception_notifier_
.bind (handle
,
406 QObject::connect (qsock_notifier
, &QSocketNotifier::activated
, this, &ACE_QtReactor::exception_event
);
408 QObject::connect (qsock_notifier
,
409 SIGNAL (activated (ACE_QT_HANDLE_TYPE
)),
411 SLOT (exception_event (ACE_QT_HANDLE_TYPE
))) ;
413 // disable; it will be enabled by the regular register_handler_i if
415 qsock_notifier
->setEnabled (0);
420 ACE_QtReactor::destroy_notifiers_for_handle (ACE_HANDLE handle
)
422 QSocketNotifier
*qsock_notifier
= 0;
424 // Looks for the handle in the maps and removes them.
426 if ((this->read_notifier_
.find (handle
,
427 qsock_notifier
) != -1))
429 this->read_notifier_
.unbind (handle
,
431 delete qsock_notifier
;
434 if ((this->write_notifier_
.find (handle
,
435 qsock_notifier
) != -1))
437 this->write_notifier_
.unbind (handle
,
439 delete qsock_notifier
;
443 if ((this->exception_notifier_
.find (handle
,
444 qsock_notifier
) != -1))
446 this->exception_notifier_
.unbind (handle
,
448 delete qsock_notifier
;
453 ACE_QtReactor::register_handler_i (ACE_HANDLE handle
,
454 ACE_Event_Handler
*handler
,
455 ACE_Reactor_Mask mask
)
457 ACE_TRACE ("ACE_QtReactor::register_handler_i");
459 this->create_notifiers_for_handle (handle
);
462 if ((result
= ACE_Select_Reactor::register_handler_i(handle
,
467 // destroy notifiers only when there is no handler for handle
468 if ( !ACE_Select_Reactor::find_handler( handle
) )
469 this->destroy_notifiers_for_handle (handle
);
477 ACE_QtReactor::register_handler_i (const ACE_Handle_Set
&handles
,
478 ACE_Event_Handler
*handler
,
479 ACE_Reactor_Mask mask
)
481 return ACE_Select_Reactor::register_handler_i(handles
,
486 int ACE_QtReactor::remove_handler_i (ACE_HANDLE handle
,
487 ACE_Reactor_Mask mask
)
489 ACE_TRACE ("ACE_QtReactor::remove_handler_i");
491 int result
= ACE_Select_Reactor::remove_handler_i (handle
, mask
);
492 // destroy notifiers only when there is no handler for handle
493 if ( !ACE_Select_Reactor::find_handler( handle
) )
494 this->destroy_notifiers_for_handle (handle
);
500 ACE_QtReactor::remove_handler_i (const ACE_Handle_Set
&handles
,
501 ACE_Reactor_Mask mask
)
503 return ACE_Select_Reactor::remove_handler_i (handles
,
507 // The following functions ensure that there is an Qt timeout for the
508 // first timeout in the Reactor's Timer_Queue.
511 ACE_QtReactor::reset_timeout ()
513 if (this->qtime_
!= 0)
519 ACE_Time_Value
*max_wait_time
=
520 this->timer_queue_
->calculate_timeout (0) ;
524 ACE_NEW (this->qtime_
,
527 QObject::connect (qtime_
,
530 SLOT (timeout_event ()));
532 #if QT_VERSION >= 0x040000
533 qtime_
->setSingleShot (1);
534 qtime_
->start(max_wait_time
->msec());
536 qtime_
->start(max_wait_time
->msec(), 1);
544 ACE_QtReactor::schedule_timer (ACE_Event_Handler
*handler
,
546 const ACE_Time_Value
&delay_time
,
547 const ACE_Time_Value
&interval
)
549 ACE_TRACE ("ACE_QtReactor::schedule_timer");
550 ACE_MT (ACE_GUARD_RETURN (ACE_Select_Reactor_Token
,
556 if ((result
= ACE_Select_Reactor::schedule_timer(handler
,
563 this->reset_timeout ();
569 ACE_QtReactor::cancel_timer (ACE_Event_Handler
*handler
,
570 int dont_call_handle_close
)
572 ACE_TRACE ("ACE_QtReactor::cancel_timer");
574 if (ACE_Select_Reactor::cancel_timer (handler
,
575 dont_call_handle_close
) == -1 )
579 this->reset_timeout( ) ;
584 int ACE_QtReactor::cancel_timer (long timer_id
,
586 int dont_call_handle_close
)
588 ACE_TRACE ("ACE_QtReactor::cancel_timer") ;
590 if (ACE_Select_Reactor::cancel_timer (timer_id
,
592 dont_call_handle_close
) == -1 )
596 this->reset_timeout( ) ;
601 // mbrudka: who needs QtWaitForMultipleEvents? It seems it's cargo load now!
603 ACE_QtReactor::QtWaitForMultipleEvents (int width
,
604 ACE_Select_Reactor_Handle_Set
&wait_set
,
605 ACE_Time_Value
* /*max_wait_time*/)
607 // Keep a copy of the wait set in case the wait_set be changed
608 // between the two select calls in this function. It could happen
609 // while waiting for an event, another event is handled and dispatched
610 // which changes the dispatch_set_/wait_set.
611 ACE_Select_Reactor_Handle_Set orig_wait_set
= wait_set
;
613 // Check to make sure our handle's are all usable.
614 ACE_Select_Reactor_Handle_Set temp_set
= wait_set
;
616 if (ACE_OS::select (width
,
620 (ACE_Time_Value
*) &ACE_Time_Value::zero
) == -1)
621 return -1; // Bad file arguments...
624 #if QT_VERSION >= 0x040000
625 this->qapp_
->processEvents();
627 this->qapp_
->processOneEvent ();
630 // Reset the width, in case it changed during the upcalls.
631 width
= static_cast<int> (handler_rep_
.max_handlep1 ());
633 // Now actually read the result needed by the <Select_Reactor> using
635 return ACE_OS::select(width
,
636 orig_wait_set
.rd_mask_
,
637 orig_wait_set
.wr_mask_
,
638 orig_wait_set
.ex_mask_
,
639 (ACE_Time_Value
*) &ACE_Time_Value::zero
);
642 // mbrudka: who needs wait_for_multiple_events? It seems it's cargo load now!
644 ACE_QtReactor::wait_for_multiple_events (
645 ACE_Select_Reactor_Handle_Set
&handle_set
,
646 ACE_Time_Value
*max_wait_time
)
648 ACE_TRACE ("ACE_QtReactor::wait_for_multiple_events");
653 max_wait_time
= this->timer_queue_
->calculate_timeout (max_wait_time
);
654 size_t width
= this->handler_rep_
.max_handlep1 ();
655 handle_set
.rd_mask_
= this->wait_set_
.rd_mask_
;
656 handle_set
.wr_mask_
= this->wait_set_
.wr_mask_
;
657 handle_set
.ex_mask_
= this->wait_set_
.ex_mask_
;
659 nfound
= QtWaitForMultipleEvents (static_cast<int> (width
),
662 } while( nfound
== -1 && this->handle_error () > 0 );
666 #if !defined (ACE_WIN32)
667 handle_set
.rd_mask_
.sync (this->handler_rep_
.max_handlep1 ());
668 handle_set
.wr_mask_
.sync (this->handler_rep_
.max_handlep1 ());
669 handle_set
.ex_mask_
.sync (this->handler_rep_
.max_handlep1 ());
670 #endif /* ACE_WIN32 */
674 // Timed out or input available
677 ACE_END_VERSIONED_NAMESPACE_DECL