Merge pull request #2309 from mitza-oci/warnings
[ACE_TAO.git] / ACE / ace / QtReactor / QtReactor.cpp
blob2cb897dba235f3fac9b32fe78bd3c644a3ad3b95
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 ,
9 ACE_Sig_Handler *sh,
10 ACE_Timer_Queue *tq,
11 int disable_notify_pipe,
12 ACE_Reactor_Notify *notify,
13 bool mask_signals,
14 int s_queue ):
15 ACE_Select_Reactor( sh, tq, disable_notify_pipe,
16 notify, mask_signals, s_queue),
17 qapp_(qapp),
18 qtime_ (0)
20 reopen_notification_pipe();
23 // Must be called with lock held
24 ACE_QtReactor::ACE_QtReactor (size_t size,
25 QApplication *qapp,
26 bool restart,
27 ACE_Sig_Handler *sh,
28 ACE_Timer_Queue *tq,
29 int disable_notify_pipe,
30 ACE_Reactor_Notify *notify,
31 bool mask_signals,
32 int s_queue):
33 ACE_Select_Reactor( size, restart, sh, tq,
34 disable_notify_pipe, notify, mask_signals,
35 s_queue ),
36 qapp_(qapp),
37 qtime_ (0)
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)
57 if ( initialized_ )
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
79 delete entry.int_id_;
80 ++iter;
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
90 delete entry.int_id_;
91 ++iter;
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_;
102 ++iter;
105 // QOBject destructor notifies qapplication (hopefully) on delete
106 delete qtime_;
109 void
110 ACE_QtReactor::qapplication (QApplication *qapp)
112 // reparent QSocketNotifiers and QTimer
113 qapp_ = qapp ;
116 void
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 ();
127 #ifdef ACE_HAS_QT5
128 ACE_HANDLE
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;
136 #endif
138 void
139 ACE_QtReactor::read_event (ACE_QT_HANDLE_TYPE p_handle)
141 ACE_TRACE ("ACE_QtReactor::read_event");
143 #ifdef ACE_HAS_QT5
144 ACE_UNUSED_ARG (p_handle);
145 ACE_HANDLE const handle = this->handle_from_sender ();
146 #else
147 ACE_HANDLE handle = ACE_HANDLE( p_handle );
148 #endif
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 );
168 if ( -1 != mask )
169 set_enable_flag_by_mask ( 1, handle, mask);
170 #endif /* ACE_QTREACTOR_CLEAR_PENDING_EVENTS */
173 void
174 ACE_QtReactor::write_event (ACE_QT_HANDLE_TYPE p_handle)
176 ACE_TRACE ("ACE_QtReactor::write_event");
178 #ifdef ACE_HAS_QT5
179 ACE_UNUSED_ARG (p_handle);
180 ACE_HANDLE const handle = this->handle_from_sender ();
181 #else
182 ACE_HANDLE handle = ACE_HANDLE( p_handle );
183 #endif
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 );
202 if ( -1 != mask )
203 set_enable_flag_by_mask ( 1, handle, mask);
204 #endif /* ACE_QTREACTOR_CLEAR_PENDING_EVENTS */
207 void
208 ACE_QtReactor::exception_event (ACE_QT_HANDLE_TYPE p_handle)
210 ACE_TRACE ("ACE_QtReactor::exception_event");
212 #ifdef ACE_HAS_QT5
213 ACE_UNUSED_ARG (p_handle);
214 ACE_HANDLE const handle = this->handle_from_sender ();
215 #else
216 ACE_HANDLE handle = ACE_HANDLE( p_handle );
217 #endif
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 );
236 if ( -1 != 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,
243 ACE_HANDLE handle,
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
252 qs_not = 0;
253 if ((this->read_notifier_.find (handle, qs_not) == -1))
254 return -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))
263 qs_not = 0;
264 if ((this->write_notifier_.find (handle, qs_not) == -1))
265 return -1;
267 qs_not->setEnabled (flag_value);
270 if (ACE_BIT_ENABLED( mask,
271 ACE_Event_Handler::EXCEPT_MASK))
273 qs_not = 0;
274 if ((this->exception_notifier_.find (handle, qs_not) == -1))
275 return -1;
277 qs_not->setEnabled (flag_value);
280 return 0;
284 ACE_QtReactor::bit_ops (ACE_HANDLE handle,
285 ACE_Reactor_Mask mask,
286 ACE_Select_Reactor_Handle_Set &handle_set,
287 int ops)
289 int result;
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)
294 return -1;
296 // disable or enable the notifiers based on handle_set and mask
297 int enableFlag = -1;
298 if (&handle_set == &this->suspend_set_)
299 enableFlag = 0;
300 else if (&handle_set == &this->wait_set_)
301 enableFlag = 1;
302 else
303 // We have no work to do here, so just return
304 return result;
306 switch (ops)
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;
316 return -1;
318 break;
320 case ACE_Reactor::CLR_MASK:
321 if (this->set_enable_flag_by_mask (!enableFlag, handle, mask) == -1)
323 handle_set = preserved_handle_set;
324 return -1;
326 break;
328 default:
329 // we take no action for any other operations
330 break;
333 return result;
336 void
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,
349 qsock_notifier);
351 #ifdef ACE_HAS_QT5
352 QObject::connect (qsock_notifier, &QSocketNotifier::activated, this, &ACE_QtReactor::read_event);
353 #else
354 QObject::connect (qsock_notifier,
355 SIGNAL (activated (ACE_QT_HANDLE_TYPE)),
356 this,
357 SLOT (read_event (ACE_QT_HANDLE_TYPE))) ;
358 #endif
359 // disable; it will be enabled by the regular register_handler_i if
360 // necessary
361 qsock_notifier->setEnabled (0);
364 qsock_notifier = 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,
376 qsock_notifier);
378 #ifdef ACE_HAS_QT5
379 QObject::connect (qsock_notifier, &QSocketNotifier::activated, this, &ACE_QtReactor::write_event);
380 #else
381 QObject::connect (qsock_notifier,
382 SIGNAL (activated (ACE_QT_HANDLE_TYPE)),
383 this,
384 SLOT (write_event (ACE_QT_HANDLE_TYPE)));
385 #endif
386 // disable; it will be enabled by the regular register_handler_i if
387 // necessary
388 qsock_notifier->setEnabled (0);
392 qsock_notifier = 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,
403 qsock_notifier);
405 #ifdef ACE_HAS_QT5
406 QObject::connect (qsock_notifier, &QSocketNotifier::activated, this, &ACE_QtReactor::exception_event);
407 #else
408 QObject::connect (qsock_notifier,
409 SIGNAL (activated (ACE_QT_HANDLE_TYPE)),
410 this,
411 SLOT (exception_event (ACE_QT_HANDLE_TYPE))) ;
412 #endif
413 // disable; it will be enabled by the regular register_handler_i if
414 // necessary
415 qsock_notifier->setEnabled (0);
419 void
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,
430 qsock_notifier);
431 delete qsock_notifier;
434 if ((this->write_notifier_.find (handle,
435 qsock_notifier) != -1))
437 this->write_notifier_.unbind (handle,
438 qsock_notifier);
439 delete qsock_notifier;
443 if ((this->exception_notifier_.find (handle,
444 qsock_notifier) != -1))
446 this->exception_notifier_.unbind (handle,
447 qsock_notifier);
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);
461 int result;
462 if ((result = ACE_Select_Reactor::register_handler_i(handle,
463 handler,
464 mask ))
465 == -1)
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);
470 return -1;
473 return 0;
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,
482 handler,
483 mask);
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);
495 return result;
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,
504 mask);
507 // The following functions ensure that there is an Qt timeout for the
508 // first timeout in the Reactor's Timer_Queue.
510 void
511 ACE_QtReactor::reset_timeout ()
513 if (this->qtime_ != 0)
515 delete this->qtime_;
516 this->qtime_ = 0;
519 ACE_Time_Value *max_wait_time =
520 this->timer_queue_->calculate_timeout (0) ;
522 if (max_wait_time)
524 ACE_NEW (this->qtime_,
525 QTimer);
527 QObject::connect (qtime_,
528 SIGNAL (timeout ()),
529 this,
530 SLOT (timeout_event ()));
532 #if QT_VERSION >= 0x040000
533 qtime_->setSingleShot (1);
534 qtime_->start(max_wait_time->msec());
535 #else
536 qtime_->start(max_wait_time->msec(), 1);
537 #endif
543 long
544 ACE_QtReactor::schedule_timer (ACE_Event_Handler *handler,
545 const void *arg,
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,
551 ace_mon,
552 this->token_,
553 -1));
555 long result;
556 if ((result = ACE_Select_Reactor::schedule_timer(handler,
557 arg,
558 delay_time,
559 interval)) == -1 )
560 return -1;
561 else
563 this->reset_timeout ();
564 return result;
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 )
576 return -1 ;
577 else
579 this->reset_timeout( ) ;
580 return 0 ;
584 int ACE_QtReactor::cancel_timer (long timer_id,
585 const void **arg,
586 int dont_call_handle_close )
588 ACE_TRACE ("ACE_QtReactor::cancel_timer") ;
590 if (ACE_Select_Reactor::cancel_timer (timer_id,
591 arg,
592 dont_call_handle_close ) == -1 )
593 return -1 ;
594 else
596 this->reset_timeout( ) ;
597 return 0 ;
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,
617 temp_set.rd_mask_,
618 temp_set.wr_mask_,
619 temp_set.ex_mask_,
620 (ACE_Time_Value *) &ACE_Time_Value::zero ) == -1)
621 return -1; // Bad file arguments...
623 // Qt processing.
624 #if QT_VERSION >= 0x040000
625 this->qapp_->processEvents();
626 #else
627 this->qapp_->processOneEvent ();
628 #endif
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
634 // <select>.
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");
650 int nfound = 0;
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),
660 handle_set,
661 max_wait_time);
662 } while( nfound == -1 && this->handle_error () > 0 );
664 if (nfound > 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 */
673 return nfound;
674 // Timed out or input available
677 ACE_END_VERSIONED_NAMESPACE_DECL