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