Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qabstracteventdispatcher.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
8
9#include "qthread.h"
10#include <private/qthread_p.h>
11#include <private/qcoreapplication_p.h>
12#include <private/qfreelist_p.h>
13
14#include <QtCore/q26numeric.h>
15
17
18using namespace std::chrono_literals;
19
20// we allow for 2^24 = 8^8 = 16777216 simultaneously running timers
22{
23 enum
24 {
27 };
28
29 static const int Sizes[BlockCount];
30};
31
32enum {
33 Offset0 = 0x00000000,
34 Offset1 = 0x00000040,
35 Offset2 = 0x00000100,
36 Offset3 = 0x00001000,
37 Offset4 = 0x00010000,
38 Offset5 = 0x00100000,
39
45 Size5 = QtTimerIdFreeListConstants::MaxIndex - Offset5
46};
47
56
58Q_GLOBAL_STATIC(QtTimerIdFreeList, timerIdFreeList)
59
60template <typename T> static T fromDuration(std::chrono::nanoseconds interval)
61{
62 using namespace std::chrono;
63 qint64 value = ceil<milliseconds>(interval).count();
64 return q26::saturate_cast<T>(value);
65}
66
67#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
68static inline QAbstractEventDispatcherV2 *v2(QAbstractEventDispatcher *self)
69{
70 if (QAbstractEventDispatcherPrivate::get(self)->isV2)
71 return static_cast<QAbstractEventDispatcherV2 *>(self);
72 return nullptr;
73}
74
75static inline const QAbstractEventDispatcherV2 *v2(const QAbstractEventDispatcher *self)
76{
77 if (QAbstractEventDispatcherPrivate::get(self)->isV2)
78 return static_cast<const QAbstractEventDispatcherV2 *>(self);
79 return nullptr;
80}
81#endif // Qt 7
82
83QAbstractEventDispatcherPrivate::QAbstractEventDispatcherPrivate()
84{
85 // Create the timer ID free list here to make sure that it is destroyed
86 // after any global static thread that may be using it.
87 // See also QTBUG-58732.
88 if (!timerIdFreeList.isDestroyed())
89 (void)timerIdFreeList();
90}
91
92QAbstractEventDispatcherPrivate::~QAbstractEventDispatcherPrivate()
93 = default;
94
95Qt::TimerId QAbstractEventDispatcherPrivate::allocateTimerId()
96{
97 // This function may be called after timerIdFreeList() has been destructed
98 // for example in case when application exits without waiting for
99 // running threads to exit and running thread finished() has been connected
100 // to a slot which triggers a sequence that registers new timer.
101 // See https://bugreports.qt-project.org/browse/QTBUG-38957.
102 if (QtTimerIdFreeList *fl = timerIdFreeList())
103 return Qt::TimerId{fl->next()};
104 return Qt::TimerId{0}; // Note! returning 0 generates a warning
105}
106
107void QAbstractEventDispatcherPrivate::releaseTimerId(Qt::TimerId timerId)
108{
109 // this function may be called by a global destructor after
110 // timerIdFreeList() has been destructed
111 if (QtTimerIdFreeList *fl = timerIdFreeList())
112 fl->release(qToUnderlying(timerId));
113}
114
115/*!
116 \class QAbstractEventDispatcher
117 \inmodule QtCore
118 \brief The QAbstractEventDispatcher class provides an interface to manage Qt's event queue.
119
120 \ingroup events
121
122 An event dispatcher receives events from the window system and other
123 sources. It then sends them to the QCoreApplication or QApplication
124 instance for processing and delivery. QAbstractEventDispatcher provides
125 fine-grained control over event delivery.
126
127 For simple control of event processing use
128 QCoreApplication::processEvents().
129
130 For finer control of the application's event loop, call
131 instance() and call functions on the QAbstractEventDispatcher
132 object that is returned. If you want to use your own instance of
133 QAbstractEventDispatcher or of a QAbstractEventDispatcher
134 subclass, you must install it with QCoreApplication::setEventDispatcher()
135 or QThread::setEventDispatcher() \e before a default event dispatcher has
136 been installed.
137
138 The main event loop is started by calling
139 QCoreApplication::exec(), and stopped by calling
140 QCoreApplication::exit(). Local event loops can be created using
141 QEventLoop.
142
143 Programs that perform long operations can call processEvents()
144 with a bitwise OR combination of various QEventLoop::ProcessEventsFlag
145 values to control which events should be delivered.
146
147 QAbstractEventDispatcher also allows the integration of an
148 external event loop with the Qt event loop.
149
150 \sa QEventLoop, QCoreApplication, QThread
151*/
152/*!
153 \typedef QAbstractEventDispatcher::Duration
154
155 A \c{std::chrono::duration} type that is used in various API in this class.
156 This type exists to facilitate a possible transition to a higher or lower
157 granularity.
158
159 In all current platforms, it is \c nanoseconds.
160*/
161
162/*!
163 Constructs a new event dispatcher with the given \a parent.
164*/
165QAbstractEventDispatcher::QAbstractEventDispatcher(QObject *parent)
166 : QObject(*new QAbstractEventDispatcherPrivate, parent) {}
167
168/*!
169 \internal
170*/
171QAbstractEventDispatcher::QAbstractEventDispatcher(QAbstractEventDispatcherPrivate &dd,
172 QObject *parent)
173 : QObject(dd, parent) {}
174
175/*!
176 Destroys the event dispatcher.
177*/
178QAbstractEventDispatcher::~QAbstractEventDispatcher()
179{
180 // don't recreate the QThreadData if it has already been destroyed
181 QThreadData *data = QThreadData::currentThreadData();
182 if (data && data->eventDispatcher.loadRelaxed() == this)
183 data->eventDispatcher.storeRelaxed(nullptr);
184}
185
186/*!
187 Returns a pointer to the event dispatcher object for the specified
188 \a thread. If \a thread is \nullptr, the current thread is used. If no
189 event dispatcher exists for the specified thread, this function
190 returns \nullptr.
191
192 \b{Note:} If Qt is built without thread support, the \a thread
193 argument is ignored.
194 */
195QAbstractEventDispatcher *QAbstractEventDispatcher::instance(QThread *thread)
196{
197 // do create a QThreadData, in case this is very early in an adopted thread
198 QThreadData *data = thread ? QThreadData::get2(thread) : QThreadData::current();
199 return data->eventDispatcher.loadRelaxed();
200}
201
202/*!
203 \fn bool QAbstractEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
204
205 Processes pending events that match \a flags until there are no
206 more events to process. Returns \c true if an event was processed;
207 otherwise returns \c false.
208
209 This function is especially useful if you have a long running
210 operation, and want to show its progress without allowing user
211 input by using the QEventLoop::ExcludeUserInputEvents flag.
212
213 If the QEventLoop::WaitForMoreEvents flag is set in \a flags, the
214 behavior of this function is as follows:
215
216 \list
217
218 \li If events are available, this function returns after processing
219 them.
220
221 \li If no events are available, this function will wait until more
222 are available and return after processing newly available events.
223
224 \endlist
225
226 If the QEventLoop::WaitForMoreEvents flag is not set in \a flags,
227 and no events are available, this function will return
228 immediately.
229
230 \b{Note:} This function does not process events continuously; it
231 returns after all available events are processed.
232*/
233
234/*!
235 \internal
236
237 \note processEvents() only processes events queued before the function
238 is called. Events that are posted while the function runs will be queued
239 until a later round of event processing. This only applies to posted Qt
240 events. For timers and system level events, the situation is unknown.
241*/
242
243/*!
244 \fn void QAbstractEventDispatcher::registerSocketNotifier(QSocketNotifier *notifier)
245
246 Registers \a notifier with the event loop. Subclasses must
247 implement this method to tie a socket notifier into another
248 event loop.
249*/
250
251/*! \fn void QAbstractEventDispatcher::unregisterSocketNotifier(QSocketNotifier *notifier)
252
253 Unregisters \a notifier from the event dispatcher. Subclasses must
254 reimplement this method to tie a socket notifier into another
255 event loop. Reimplementations must call the base
256 implementation.
257*/
258
259/*!
260 \obsolete [6.8] This function will be removed in Qt 7. Use the overload taking \l Duration.
261
262 Registers a timer with the specified \a interval and \a timerType for the
263 given \a object and returns the timer id.
264*/
265int QAbstractEventDispatcher::registerTimer(qint64 interval, Qt::TimerType timerType, QObject *object)
266{
267 return int(registerTimer(interval * 1ms, timerType, object));
268}
269
270/*!
271 \since 6.8
272 \overload
273
274 Registers a timer with the specified \a interval and \a timerType for the
275 given \a object and returns the timer id.
276*/
277Qt::TimerId QAbstractEventDispatcher::registerTimer(Duration interval, Qt::TimerType timerType,
278 QObject *object)
279{
280 auto id = QAbstractEventDispatcherPrivate::allocateTimerId();
281#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
282 if (QAbstractEventDispatcherV2 *self = v2(this))
283 self->registerTimer(id, interval, timerType, object);
284 else
285 registerTimer(qToUnderlying(id), fromDuration<qint64>(interval), timerType, object);
286#else
287 registerTimer(id, interval, timerType, object);
288#endif
289 return id;
290}
291
292#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
293/*!
294 \fn void QAbstractEventDispatcher::registerTimer(int timerId, qint64 interval, Qt::TimerType timerType, QObject *object)
295
296 Register a timer with the specified \a timerId, \a interval, and \a
297 timerType for the given \a object.
298*/
299
300/*!
301 \fn bool QAbstractEventDispatcher::unregisterTimer(int timerId)
302
303 Unregisters the timer with the given \a timerId.
304 Returns \c true if successful; otherwise returns \c false.
305
306 \sa registerTimer(), unregisterTimers()
307*/
308
309/*!
310 \fn QList<TimerInfo> QAbstractEventDispatcher::registeredTimers(QObject *object) const
311
312 Returns a list of registered timers for \a object. The TimerInfo struct has
313 \c timerId, \c interval, and \c timerType members.
314
315 \sa Qt::TimerType
316*/
317
318/*!
319 \fn int QAbstractEventDispatcher::remainingTime(int timerId)
320
321 Returns the remaining time in milliseconds with the given \a timerId.
322 If the timer is inactive, the returned value will be -1. If the timer is
323 overdue, the returned value will be 0.
324
325 \sa Qt::TimerType
326*/
327#else // Qt 7
328/*!
329 \fn void QAbstractEventDispatcher::registerTimer(Qt::TimerId timerId, Duration interval, Qt::TimerType timerType, QObject *object)
330 \since 6.8
331
332 Register a timer with the specified \a timerId, \a interval, and \a
333 timerType for the given \a object.
334
335 \sa unregisterTimer(), timersForObject()
336*/
337
338/*!
339 \fn bool QAbstractEventDispatcher::unregisterTimer(Qt::TimerId timerId)
340 \since 6.8
341
342 Unregisters the timer with the given \a timerId.
343 Returns \c true if successful; otherwise returns \c false.
344
345 \sa registerTimer(), unregisterTimers()
346*/
347
348/*!
349 \fn QList<TimerInfoV2> QAbstractEventDispatcher::timersForObject(QObject *object) const
350 \since 6.8
351
352 Returns a list of registered timers for \a object. The TimerInfoV2 struct has
353 \c timerId, \c interval, and \c timerType members.
354
355 \sa Qt::TimerType, registerTimer(), unregisterTimer()
356*/
357
358/*!
359 \fn QAbstractEventDispatcher::remainingTime(Qt::TimerId timerId) const
360
361 Returns the remaining time of the timer with the given \a timerId.
362 If the timer is inactive, the returned value will be negative. If the timer
363 is overdue, the returned value will be 0.
364
365 \sa Qt::TimerType, registerTimer(), unregisterTimer()
366*/
367#endif
368
369/*!
370 \fn bool QAbstractEventDispatcher::unregisterTimers(QObject *object)
371
372 Unregisters all the timers associated with the given \a object. Returns \c
373 true if all timers were successfully removed; otherwise returns \c false.
374
375 \sa unregisterTimer(), registeredTimers()
376*/
377
378
379/*! \fn void QAbstractEventDispatcher::wakeUp()
380 \threadsafe
381
382 Wakes up the event loop.
383
384 \omit
385 ### FIXME - QTBUG-70229
386 On Unix and Glib event dispatchers, if the dispatcher is already awake when
387 this function is called, it is ensured that the current iteration won't block
388 waiting for more events, but will instead do another event loop iteration.
389
390 ### TODO - does other event dispatchers behave the same?
391 \endomit
392
393 \sa awake()
394*/
395
396/*!
397 \fn void QAbstractEventDispatcher::interrupt()
398
399 Interrupts event dispatching. The event dispatcher will
400 return from processEvents() as soon as possible.
401*/
402
403// ### DOC: Are these called when the _application_ starts/stops or just
404// when the current _event loop_ starts/stops?
405/*!
406 \internal
407*/
408void QAbstractEventDispatcher::startingUp()
409{ }
410
411/*!
412 \internal
413*/
414void QAbstractEventDispatcher::closingDown()
415{ }
416
417/*!
418 \class QAbstractEventDispatcher::TimerInfo
419 \deprecated [6.8] Use TimerInfoV2
420 \inmodule QtCore
421
422 This struct represents information about a timer:
423 \l{QAbstractEventDispatcher::TimerInfo::timerId}{timerId},
424 \l{QAbstractEventDispatcher::TimerInfo::interval}{interval}, and
425 \l{QAbstractEventDispatcher::TimerInfo::timerType}{timerType}.
426
427 \sa registeredTimers(), QAbstractEventDispatcher::TimerInfoV2, timersForObject()
428*/
429/*!
430 \variable QAbstractEventDispatcher::TimerInfo::timerId
431
432 The timer's unique id.
433*/
434/*!
435 \variable QAbstractEventDispatcher::TimerInfo::interval
436
437 The timer's interval.
438*/
439/*!
440 \variable QAbstractEventDispatcher::TimerInfo::timerType
441
442 The timer's type
443
444 \sa Qt::TimerType
445*/
446
447/*!
448 \class QAbstractEventDispatcher::TimerInfoV2
449 \inmodule QtCore
450
451 This struct represents information about a timer:
452 \l{QAbstractEventDispatcher::TimerInfoV2::timerId}{timerId},
453 \l{QAbstractEventDispatcher::TimerInfoV2::interval}{interval}, and
454 \l{QAbstractEventDispatcher::TimerInfoV2::timerType}{timerType}.
455
456 \sa timersForObject()
457*/
458/*!
459 \variable QAbstractEventDispatcher::TimerInfoV2::timerId
460
461 The timer's unique id. This is created by registerTimer() upon creation and
462 uniquely identifies a timer while it is active. It is also used by
463 QTimer::id() and returned by QObject::startTimer().
464*/
465/*!
466 \variable QAbstractEventDispatcher::TimerInfoV2::interval
467
468 The timer's interval.
469*/
470/*!
471 \variable QAbstractEventDispatcher::TimerInfoV2::timerType
472
473 The timer's type
474
475 \sa Qt::TimerType
476*/
477
478/*!
479 Installs an event filter \a filterObj for all native events received by the application.
480
481 The event filter \a filterObj receives events via its \l {QAbstractNativeEventFilter::}{nativeEventFilter()}
482 function, which is called for all events received by all threads.
483
484 The \l {QAbstractNativeEventFilter::}{nativeEventFilter()} function should return true
485 if the event should be filtered, (in this case, stopped). It should return false to allow
486 normal Qt processing to continue: the native event can then be translated
487 into a QEvent and handled by the standard Qt \l{QEvent} {event} filtering,
488 e.g. QObject::installEventFilter().
489
490 If multiple event filters are installed, the filter that was installed last
491 is activated first.
492
493 \note The filter function set here receives native messages,
494 that is, MSG or XEvent structs.
495
496 For maximum portability, you should always try to use QEvent objects
497 and QObject::installEventFilter() whenever possible.
498
499 \sa QObject::installEventFilter()
500
501 \since 5.0
502*/
503void QAbstractEventDispatcher::installNativeEventFilter(QAbstractNativeEventFilter *filterObj)
504{
505 Q_D(QAbstractEventDispatcher);
506
507 // clean up unused items in the list
508 d->eventFilters.removeAll(nullptr);
509 d->eventFilters.removeAll(filterObj);
510 d->eventFilters.prepend(filterObj);
511}
512
513/*!
514 Removes the event filter \a filter from this object. The
515 request is ignored if such an event filter has not been installed.
516
517 All event filters for this object are automatically removed when
518 this object is destroyed.
519
520 It is always safe to remove an event filter, even during event filter
521 filter activation (that is, even from within the \l {QAbstractNativeEventFilter::}{nativeEventFilter()} function).
522
523 \sa installNativeEventFilter(), QAbstractNativeEventFilter
524 \since 5.0
525*/
526void QAbstractEventDispatcher::removeNativeEventFilter(QAbstractNativeEventFilter *filter)
527{
528 Q_D(QAbstractEventDispatcher);
529 if (const auto idx = d->eventFilters.indexOf(filter); idx >= 0)
530 d->eventFilters[idx] = nullptr;
531}
532
533/*!
534 Sends \a message through the event filters that were set by
535 installNativeEventFilter(). This function returns \c true as soon as an
536 event filter returns \c true, and false otherwise to indicate that
537 the processing of the event should continue.
538
539 Subclasses of QAbstractEventDispatcher \e must call this function
540 for \e all messages received from the system to ensure
541 compatibility with any extensions that may be used in the
542 application. The type of event \a eventType is specific to the platform
543 plugin chosen at run-time, and can be used to cast message to the right type.
544 The \a result pointer is only used on Windows, and corresponds to the LRESULT pointer.
545
546 Note that the type of \a message is platform dependent. See
547 QAbstractNativeEventFilter for details.
548
549 \sa installNativeEventFilter(), QAbstractNativeEventFilter::nativeEventFilter()
550 \since 5.0
551*/
552bool QAbstractEventDispatcher::filterNativeEvent(const QByteArray &eventType, void *message, qintptr *result)
553{
554 Q_D(QAbstractEventDispatcher);
555 if (!d->eventFilters.isEmpty()) {
556 // Raise the loopLevel so that deleteLater() calls in or triggered
557 // by event_filter() will be processed from the main event loop.
558 QScopedScopeLevelCounter scopeLevelCounter(d->threadData.loadAcquire());
559 for (qsizetype i = 0; i < d->eventFilters.size(); ++i) {
560 QAbstractNativeEventFilter *filter = d->eventFilters.at(i);
561 if (!filter)
562 continue;
563 if (filter->nativeEventFilter(eventType, message, result))
564 return true;
565 }
566 }
567 return false;
568}
569
570/*! \fn void QAbstractEventDispatcher::awake()
571
572 This signal is emitted after the event loop returns from a
573 function that could block.
574
575 \sa wakeUp(), aboutToBlock()
576*/
577
578/*! \fn void QAbstractEventDispatcher::aboutToBlock()
579
580 This signal is emitted before the event loop calls a function that
581 could block.
582
583 \sa awake()
584*/
585
586#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
587void QAbstractEventDispatcher::registerTimer(Qt::TimerId timerId, Duration interval,
588 Qt::TimerType timerType, QObject *object)
589{
590 if (QAbstractEventDispatcherV2 *self = v2(this))
591 self->registerTimer(timerId, interval, timerType, object);
592 else
593 registerTimer(int(timerId), fromDuration<qint64>(interval), timerType, object);
594}
595
596bool QAbstractEventDispatcher::unregisterTimer(Qt::TimerId timerId)
597{
598 if (QAbstractEventDispatcherV2 *self = v2(this))
599 return self->unregisterTimer(timerId);
600 return unregisterTimer(int(timerId));
601}
602
603QList<QAbstractEventDispatcher::TimerInfoV2>
604QAbstractEventDispatcher::timersForObject(QObject *object) const
605{
606 if (const QAbstractEventDispatcherV2 *self = v2(this))
607 return self->timersForObject(object);
608 QList<TimerInfo> timers = registeredTimers(object);
609 QList<TimerInfoV2> result;
610 result.reserve(timers.size());
611 for (const TimerInfo &t : timers)
612 result.emplaceBack(TimerInfoV2{ t.interval * 1ms, Qt::TimerId(t.timerId), t.timerType });
613 return result;
614}
615
616QAbstractEventDispatcher::Duration
617QAbstractEventDispatcher::remainingTime(Qt::TimerId timerId) const
618{
619 if (const QAbstractEventDispatcherV2 *self = v2(this))
620 return self->remainingTime(timerId);
621 return const_cast<QAbstractEventDispatcher *>(this)->remainingTime(int(timerId)) * 1ms;
622}
623
624/*!
625 \class QAbstractEventDispatcherV2
626 \inmodule QtCore
627
628 This class is a temporary hack to enable transition to an API based on
629 \c{std::chrono} for the Qt event dispatcher. In Qt 7, it will be merged
630 with QAbstractEventDispatcher, replacing the pure virtuals there with the
631 ones defined here.
632
633 It is recommended applications and libraries port to the new API before
634 that future release to simplify work when the time comes.
635*/
636
637/*!
638 Constructs a new event dispatcher with the given \a parent.
639*/
640QAbstractEventDispatcherV2::QAbstractEventDispatcherV2(QObject *parent)
641 : QAbstractEventDispatcherV2(*new QAbstractEventDispatcherPrivate, parent)
642{
643}
644
645/*!
646 \internal
647*/
648QAbstractEventDispatcherV2::QAbstractEventDispatcherV2(QAbstractEventDispatcherPrivate &dd,
649 QObject *parent)
650 : QAbstractEventDispatcher((dd.isV2 = true, dd), parent)
651{
652}
653
654/*!
655 Destroys the event dispatcher.
656*/
657QAbstractEventDispatcherV2::~QAbstractEventDispatcherV2() = default;
658
659/*!
660 \internal
661 Temporary compatibility override.
662*/
663void QAbstractEventDispatcherV2::registerTimer(int timerId, qint64 interval,
664 Qt::TimerType timerType, QObject *object)
665{
666 auto self = static_cast<QAbstractEventDispatcherV2 *>(this);
667 self->registerTimer(Qt::TimerId(timerId), interval * 1ms, timerType, object);
668}
669
670/*!
671 \internal
672 Temporary compatibility override.
673*/
674bool QAbstractEventDispatcherV2::unregisterTimer(int timerId)
675{
676 auto self = static_cast<QAbstractEventDispatcherV2 *>(this);
677 return self->unregisterTimer(Qt::TimerId(timerId));
678}
679
680/*!
681 \internal
682 Temporary compatibility override.
683*/
684auto QAbstractEventDispatcherV2::registeredTimers(QObject *object) const -> QList<TimerInfo>
685{
686 auto self = static_cast<const QAbstractEventDispatcherV2 *>(this);
687 QList<TimerInfoV2> timers = self->timersForObject(object);
688 QList<TimerInfo> result;
689 result.reserve(timers.size());
690 for (const TimerInfoV2 &t : timers)
691 result.emplaceBack(qToUnderlying(t.timerId), fromDuration<int>(t.interval), t.timerType);
692 return result;
693}
694
695/*!
696 \internal
697 Temporary compatibility override.
698*/
699int QAbstractEventDispatcherV2::remainingTime(int timerId)
700{
701 auto self = static_cast<QAbstractEventDispatcherV2 *>(this);
702 return fromDuration<int>(self->remainingTime(Qt::TimerId(timerId)));
703}
704
705/*!
706 \internal
707 Temporary compatibility override.
708*/
709bool QAbstractEventDispatcherV2::processEventsWithDeadline(QEventLoop::ProcessEventsFlags flags, QDeadlineTimer deadline)
710{
711 Q_UNUSED(deadline);
712 return processEvents(flags);
713}
714#endif // ! Qt 7
715
716QT_END_NAMESPACE
717
718#include "moc_qabstracteventdispatcher.cpp"
Combined button and popup list for selecting options.
QFreeList< void, QtTimerIdFreeListConstants > QtTimerIdFreeList
static const int Sizes[BlockCount]