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
qsingleshottimer.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// Copyright (C) 2016 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4// Qt-Security score:significant reason:default
5
6#include <QtCore/private/qsingleshottimer_p.h>
7
10#include "private/qnumeric_p.h"
11#include "qthread.h"
12
14
15QSingleShotTimer::QSingleShotTimer(Duration interval, Qt::TimerType timerType,
16 const QObject *r, const char *member)
17 : QObject(QAbstractEventDispatcher::instance())
18{
19 connect(this, SIGNAL(timeout()), r, member);
20 startTimerForReceiver(interval, timerType, r);
21}
22
23QSingleShotTimer::QSingleShotTimer(Duration interval, Qt::TimerType timerType,
24 const QObject *r, QtPrivate::QSlotObjectBase *slotObj)
25 : QObject(QAbstractEventDispatcher::instance())
26{
27 int signal_index = QMetaObjectPrivate::signalOffset(&staticMetaObject);
28 Q_ASSERT(QMetaObjectPrivate::signal(&staticMetaObject, signal_index).name() == "timeout");
29 QObjectPrivate::connectImpl(this, signal_index, r ? r : this, nullptr, slotObj,
30 Qt::AutoConnection, nullptr, &staticMetaObject);
31
32 startTimerForReceiver(interval, timerType, r);
33}
34
35QSingleShotTimer::~QSingleShotTimer() = default;
36
37/*
38 Move the timer, and the dispatching and handling of the timer event, into
39 the same thread as where it will be handled, so that it fires reliably even
40 if the thread that set up the timer is busy.
41*/
42void QSingleShotTimer::startTimerForReceiver(Duration interval, Qt::TimerType timerType,
43 const QObject *receiver)
44{
45 if (receiver && receiver->thread() != thread()) {
46 QObjectPrivate *d_ptr = QObjectPrivate::get(this);
47 d_ptr->sendChildEvents = false;
48
49 setParent(nullptr);
50 moveToThread(receiver->thread());
51
52 QCoreApplication::postEvent(this,
53 new StartTimerEvent(this, QDeadlineTimer(interval, timerType)));
54 // the event owns "this" and is handled concurrently, so unsafe to
55 // access "this" beyond this point
56 } else {
57 timer.start(interval, timerType, this);
58 }
59}
60
61void QSingleShotTimer::timerFinished()
62{
63 Q_EMIT timeout();
64 delete this;
65}
66
67void QSingleShotTimer::timerEvent(QTimerEvent *event)
68{
69 if (event->id() == Qt::TimerId::Invalid) {
70 StartTimerEvent *startTimerEvent = static_cast<StartTimerEvent *>(event);
71 Q_UNUSED(startTimerEvent->timer.release()); // it's the same as "this"
72 const QDeadlineTimer &deadline = startTimerEvent->deadline;
73 if (deadline.hasExpired()) {
74 timerFinished();
75 } else {
76 timer.start(deadline.remainingTimeAsDuration(), deadline.timerType(), this);
77 // we are now definitely in a thread that has an event dispatcher
78 setParent(QThread::currentThread()->eventDispatcher());
79 }
80 } else {
81 // need to kill the timer _before_ we emit timeout() in case the
82 // slot connected to timeout calls processEvents()
83 timer.stop();
84
85 timerFinished();
86 }
87}
88
89QT_END_NAMESPACE
90
91#include "moc_qsingleshottimer_p.cpp"
Combined button and popup list for selecting options.