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
qbasictimer.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 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
5#include "qbasictimer.h"
8
9#include <private/qthread_p.h>
10
11using namespace std::chrono_literals;
12
13QT_BEGIN_NAMESPACE
14
15/*!
16 \class QBasicTimer
17 \inmodule QtCore
18 \brief The QBasicTimer class provides timer events for objects.
19
20 \ingroup events
21
22 This is a fast, lightweight, and low-level class used by Qt
23 internally. We recommend using the higher-level QTimer class
24 rather than this class if you want to use timers in your
25 applications. Note that this timer is a repeating timer that
26 will send subsequent timer events unless the stop() function is called.
27
28 To use this class, create a QBasicTimer, and call its start()
29 function with a timeout interval and with a pointer to a QObject
30 subclass. When the timer times out it will send a timer event to
31 the QObject subclass. The timer can be stopped at any time using
32 stop(). isActive() returns \c true for a timer that is running;
33 i.e. it has been started, has not reached the timeout time, and
34 has not been stopped. The timer's ID can be retrieved using
35 timerId().
36
37 Objects of this class cannot be copied, but can be moved, so you
38 can maintain a list of basic timers by holding them in container
39 that supports move-only types, e.g. std::vector.
40
41 \sa QTimer, QChronoTimer, QTimerEvent, QObject::timerEvent(),
42 Timers, {Affine Transformations}
43*/
44
45
46/*!
47 \fn QBasicTimer::QBasicTimer()
48
49 Constructs a basic timer.
50
51 \sa start()
52*/
53
54/*!
55 \fn QBasicTimer::QBasicTimer(QBasicTimer &&other)
56 \since 5.14
57
58 Move-constructs a basic timer from \a other, which is left
59 \l{isActive()}{inactive}.
60
61 \sa isActive(), swap()
62*/
63
64/*!
65 \fn QBasicTimer &QBasicTimer::operator=(QBasicTimer &&other)
66 \since 5.14
67
68 Move-assigns \a other to this basic timer. The timer
69 previously represented by this basic timer is stopped.
70 \a other is left as \l{isActive()}{inactive}.
71
72 \sa stop(), isActive(), swap()
73*/
74
75/*!
76 \fn QBasicTimer::~QBasicTimer()
77
78 Destroys the basic timer.
79*/
80
81/*!
82 \fn bool QBasicTimer::isActive() const
83
84 Returns \c true if the timer is running and has not been stopped; otherwise
85 returns \c false.
86
87 \sa start(), stop()
88*/
89
90/*!
91 \fn QBasicTimer::swap(QBasicTimer &other)
92 \since 5.14
93 \memberswap{timer}
94*/
95
96/*!
97 \fn swap(QBasicTimer &lhs, QBasicTimer &rhs)
98 \relates QBasicTimer
99 \since 5.14
100
101 Swaps the timer \a lhs with \a rhs.
102 This operation is very fast and never fails.
103*/
104
105/*!
106 \fn int QBasicTimer::timerId() const
107 \obsolete
108
109 Returns the timer's ID.
110
111 In new code use id() instead.
112
113 \sa QTimerEvent::timerId()
114*/
115
116/*!
117 \fn Qt::TimerId QBasicTimer::id() const
118 \since 6.8
119
120 Returns the timer's ID.
121
122 \sa QTimerEvent::id()
123*/
124
125/*!
126 \fn void QBasicTimer::start(int msec, QObject *object)
127
128 \obsolete Use chrono overload instead.
129*/
130
131/*!
132 \typedef QBasicTimer::Duration
133
134 A \c{std::chrono::duration} type that is used in various API in this class.
135 This type exists to facilitate a possible transition to a higher or lower
136 granularity.
137
138 In all current platforms, it is \c nanoseconds.
139*/
140
141/*!
142 \fn void QBasicTimer::start(Duration duration, QObject *object)
143 \since 6.5
144
145 Starts (or restarts) the timer with a \a duration timeout. The
146 timer will be a Qt::CoarseTimer. See Qt::TimerType for information on the
147 different timer types.
148
149 The given \a object will receive timer events.
150
151 \include timers-common.qdocinc negative-intervals-not-allowed
152
153//! [start-nanoseconds-note]
154 \note Starting from Qt 6.9 this method takes std::chrono::nanoseconds,
155 before that it took std::chrono::milliseconds. This change is
156 backwards compatible.
157//! [start-nanoseconds-note]
158
159 \sa stop(), isActive(), QObject::timerEvent(), Qt::CoarseTimer
160 */
161
162/*!
163 \fn QBasicTimer::start(int msec, Qt::TimerType timerType, QObject *obj)
164 \overload
165 \obsolete
166
167 Use chrono overload instead.
168*/
169
170/*!
171 \since 6.5
172 \overload
173
174 Starts (or restarts) the timer with a \a duration timeout and the
175 given \a timerType. See Qt::TimerType for information on the different
176 timer types.
177
178 \include timers-common.qdocinc negative-intervals-not-allowed
179
180 \a obj will receive timer events.
181
182 \include qbasictimer.cpp start-nanoseconds-note
183
184 \sa stop(), isActive(), QObject::timerEvent(), Qt::TimerType
185 */
186void QBasicTimer::start(Duration duration, Qt::TimerType timerType, QObject *obj)
187{
188 if (duration < 0ns) {
189 qWarning("QBasicTimer::start: negative intervals aren't allowed; the "
190 "interval will be set to 1ms.");
191 duration = 1ms;
192 }
193
194 QThreadData *currentData = QThreadData::current();
195 if (Q_UNLIKELY(obj && QObjectPrivate::get(obj)->threadData != currentData)) {
196 qWarning("QBasicTimer::start: Timers cannot be started from another thread");
197 return;
198 }
199
200 QAbstractEventDispatcher *eventDispatcher = currentData->eventDispatcher.loadRelaxed();
201 if (Q_UNLIKELY(!eventDispatcher)) {
202 qWarning("QBasicTimer::start: current thread's event dispatcher has already been destroyed");
203 return;
204 }
205 stop();
206 if (obj)
207 m_id = eventDispatcher->registerTimer(duration, timerType, obj);
208}
209
210/*!
211 Stops the timer.
212
213 \sa start(), isActive()
214*/
215void QBasicTimer::stop()
216{
217 if (isActive()) {
218 QAbstractEventDispatcher *eventDispatcher = nullptr;
219
220 // don't create the current thread data if it's already been destroyed
221 if (QThreadData *data = QThreadData::currentThreadData())
222 eventDispatcher = data->eventDispatcher.loadRelaxed();
223
224 if (eventDispatcher && !eventDispatcher->unregisterTimer(m_id)) {
225 qWarning("QBasicTimer::stop: Failed. Possibly trying to stop from a different thread");
226 return;
227 }
228 QAbstractEventDispatcherPrivate::releaseTimerId(m_id);
229 }
230 m_id = Qt::TimerId::Invalid;
231}
232
233QT_END_NAMESPACE