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" |
5 | #include "qabstracteventdispatcher.h" |
6 | #include "qabstracteventdispatcher_p.h" |
7 | |
8 | QT_BEGIN_NAMESPACE |
9 | |
10 | /*! |
11 | \class QBasicTimer |
12 | \inmodule QtCore |
13 | \brief The QBasicTimer class provides timer events for objects. |
14 | |
15 | \ingroup events |
16 | |
17 | This is a fast, lightweight, and low-level class used by Qt |
18 | internally. We recommend using the higher-level QTimer class |
19 | rather than this class if you want to use timers in your |
20 | applications. Note that this timer is a repeating timer that |
21 | will send subsequent timer events unless the stop() function is called. |
22 | |
23 | To use this class, create a QBasicTimer, and call its start() |
24 | function with a timeout interval and with a pointer to a QObject |
25 | subclass. When the timer times out it will send a timer event to |
26 | the QObject subclass. The timer can be stopped at any time using |
27 | stop(). isActive() returns \c true for a timer that is running; |
28 | i.e. it has been started, has not reached the timeout time, and |
29 | has not been stopped. The timer's ID can be retrieved using |
30 | timerId(). |
31 | |
32 | Objects of this class cannot be copied, but can be moved, so you |
33 | can maintain a list of basic timers by holding them in container |
34 | that supports move-only types, e.g. std::vector. |
35 | |
36 | The \l{widgets/tetrix}{Tetrix} example uses QBasicTimer to control |
37 | the rate at which pieces fall. |
38 | |
39 | \sa QTimer, QTimerEvent, QObject::timerEvent(), Timers, {Affine Transformations} |
40 | */ |
41 | |
42 | |
43 | /*! |
44 | \fn QBasicTimer::QBasicTimer() |
45 | |
46 | Constructs a basic timer. |
47 | |
48 | \sa start() |
49 | */ |
50 | |
51 | /*! |
52 | \fn QBasicTimer::QBasicTimer(QBasicTimer &&other) |
53 | \since 5.14 |
54 | |
55 | Move-constructs a basic timer from \a other, which is left |
56 | \l{isActive()}{inactive}. |
57 | |
58 | \sa isActive(), swap() |
59 | */ |
60 | |
61 | /*! |
62 | \fn QBasicTimer &QBasicTimer::operator=(QBasicTimer &&other) |
63 | \since 5.14 |
64 | |
65 | Move-assigns \a other to this basic timer. The timer |
66 | previously represented by this basic timer is stopped. |
67 | \a other is left as \l{isActive()}{inactive}. |
68 | |
69 | \sa stop(), isActive(), swap() |
70 | */ |
71 | |
72 | /*! |
73 | \fn QBasicTimer::~QBasicTimer() |
74 | |
75 | Destroys the basic timer. |
76 | */ |
77 | |
78 | /*! |
79 | \fn bool QBasicTimer::isActive() const |
80 | |
81 | Returns \c true if the timer is running and has not been stopped; otherwise |
82 | returns \c false. |
83 | |
84 | \sa start(), stop() |
85 | */ |
86 | |
87 | /*! |
88 | \fn QBasicTimer::swap(QBasicTimer &other) |
89 | \since 5.14 |
90 | |
91 | Swaps the timer \a other with this timer. |
92 | This operation is very fast and never fails. |
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 | |
107 | Returns the timer's ID. |
108 | |
109 | \sa QTimerEvent::timerId() |
110 | */ |
111 | |
112 | /*! |
113 | \fn void QBasicTimer::start(int msec, QObject *object) |
114 | |
115 | \obsolete Use chrono overload instead. |
116 | */ |
117 | |
118 | /*! |
119 | \since 6.5 |
120 | |
121 | Starts (or restarts) the timer with a \a duration timeout. The |
122 | timer will be a Qt::CoarseTimer. See Qt::TimerType for information on the |
123 | different timer types. |
124 | |
125 | The given \a object will receive timer events. |
126 | |
127 | \sa stop(), isActive(), QObject::timerEvent(), Qt::CoarseTimer |
128 | */ |
129 | void QBasicTimer::start(std::chrono::milliseconds duration, QObject *object) |
130 | { |
131 | start(duration, timerType: Qt::CoarseTimer, obj: object); |
132 | } |
133 | |
134 | /*! |
135 | \fn QBasicTimer::start(int msec, Qt::TimerType timerType, QObject *obj) |
136 | \overload |
137 | \obsolete |
138 | |
139 | Use chrono overload instead. |
140 | */ |
141 | |
142 | /*! |
143 | \since 6.5 |
144 | |
145 | Starts (or restarts) the timer with a \a duration timeout and the |
146 | given \a timerType. See Qt::TimerType for information on the different |
147 | timer types. |
148 | |
149 | \a obj will receive timer events. |
150 | |
151 | \sa stop(), isActive(), QObject::timerEvent(), Qt::TimerType |
152 | */ |
153 | void QBasicTimer::start(std::chrono::milliseconds duration, Qt::TimerType timerType, QObject *obj) |
154 | { |
155 | QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance(); |
156 | if (Q_UNLIKELY(duration.count() < 0)) { |
157 | qWarning(msg: "QBasicTimer::start: Timers cannot have negative timeouts" ); |
158 | return; |
159 | } |
160 | if (Q_UNLIKELY(!eventDispatcher)) { |
161 | qWarning(msg: "QBasicTimer::start: QBasicTimer can only be used with threads started with QThread" ); |
162 | return; |
163 | } |
164 | if (Q_UNLIKELY(obj && obj->thread() != eventDispatcher->thread())) { |
165 | qWarning(msg: "QBasicTimer::start: Timers cannot be started from another thread" ); |
166 | return; |
167 | } |
168 | stop(); |
169 | if (obj) |
170 | id = eventDispatcher->registerTimer(interval: duration.count(), timerType, object: obj); |
171 | } |
172 | |
173 | /*! |
174 | Stops the timer. |
175 | |
176 | \sa start(), isActive() |
177 | */ |
178 | void QBasicTimer::stop() |
179 | { |
180 | if (id) { |
181 | QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance(); |
182 | if (eventDispatcher && !eventDispatcher->unregisterTimer(timerId: id)) { |
183 | qWarning(msg: "QBasicTimer::stop: Failed. Possibly trying to stop from a different thread" ); |
184 | return; |
185 | } |
186 | QAbstractEventDispatcherPrivate::releaseTimerId(id); |
187 | } |
188 | id = 0; |
189 | } |
190 | |
191 | QT_END_NAMESPACE |
192 | |