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