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 | \sa QTimer, QChronoTimer, QTimerEvent, QObject::timerEvent(), |
37 | Timers, {Affine Transformations} |
38 | */ |
39 | |
40 | |
41 | /*! |
42 | \fn QBasicTimer::QBasicTimer() |
43 | |
44 | Constructs a basic timer. |
45 | |
46 | \sa start() |
47 | */ |
48 | |
49 | /*! |
50 | \fn QBasicTimer::QBasicTimer(QBasicTimer &&other) |
51 | \since 5.14 |
52 | |
53 | Move-constructs a basic timer from \a other, which is left |
54 | \l{isActive()}{inactive}. |
55 | |
56 | \sa isActive(), swap() |
57 | */ |
58 | |
59 | /*! |
60 | \fn QBasicTimer &QBasicTimer::operator=(QBasicTimer &&other) |
61 | \since 5.14 |
62 | |
63 | Move-assigns \a other to this basic timer. The timer |
64 | previously represented by this basic timer is stopped. |
65 | \a other is left as \l{isActive()}{inactive}. |
66 | |
67 | \sa stop(), isActive(), swap() |
68 | */ |
69 | |
70 | /*! |
71 | \fn QBasicTimer::~QBasicTimer() |
72 | |
73 | Destroys the basic timer. |
74 | */ |
75 | |
76 | /*! |
77 | \fn bool QBasicTimer::isActive() const |
78 | |
79 | Returns \c true if the timer is running and has not been stopped; otherwise |
80 | returns \c false. |
81 | |
82 | \sa start(), stop() |
83 | */ |
84 | |
85 | /*! |
86 | \fn QBasicTimer::swap(QBasicTimer &other) |
87 | \since 5.14 |
88 | \memberswap{timer} |
89 | */ |
90 | |
91 | /*! |
92 | \fn swap(QBasicTimer &lhs, QBasicTimer &rhs) |
93 | \relates QBasicTimer |
94 | \since 5.14 |
95 | |
96 | Swaps the timer \a lhs with \a rhs. |
97 | This operation is very fast and never fails. |
98 | */ |
99 | |
100 | /*! |
101 | \fn int QBasicTimer::timerId() const |
102 | \obsolete |
103 | |
104 | Returns the timer's ID. |
105 | |
106 | In new code use id() instead. |
107 | |
108 | \sa QTimerEvent::timerId() |
109 | */ |
110 | |
111 | /*! |
112 | \fn Qt::TimerId QBasicTimer::id() const |
113 | \since 6.8 |
114 | |
115 | Returns the timer's ID. |
116 | |
117 | \sa QTimerEvent::id() |
118 | */ |
119 | |
120 | /*! |
121 | \fn void QBasicTimer::start(int msec, QObject *object) |
122 | |
123 | \obsolete Use chrono overload instead. |
124 | */ |
125 | |
126 | /*! |
127 | \since 6.5 |
128 | |
129 | Starts (or restarts) the timer with a \a duration timeout. The |
130 | timer will be a Qt::CoarseTimer. See Qt::TimerType for information on the |
131 | different timer types. |
132 | |
133 | The given \a object will receive timer events. |
134 | |
135 | \sa stop(), isActive(), QObject::timerEvent(), Qt::CoarseTimer |
136 | */ |
137 | void QBasicTimer::start(std::chrono::milliseconds duration, QObject *object) |
138 | { |
139 | start(duration, timerType: Qt::CoarseTimer, obj: object); |
140 | } |
141 | |
142 | /*! |
143 | \fn QBasicTimer::start(int msec, Qt::TimerType timerType, QObject *obj) |
144 | \overload |
145 | \obsolete |
146 | |
147 | Use chrono overload instead. |
148 | */ |
149 | |
150 | /*! |
151 | \since 6.5 |
152 | |
153 | Starts (or restarts) the timer with a \a duration timeout and the |
154 | given \a timerType. See Qt::TimerType for information on the different |
155 | timer types. |
156 | |
157 | \a obj will receive timer events. |
158 | |
159 | \sa stop(), isActive(), QObject::timerEvent(), Qt::TimerType |
160 | */ |
161 | void QBasicTimer::start(std::chrono::milliseconds duration, Qt::TimerType timerType, QObject *obj) |
162 | { |
163 | QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance(); |
164 | if (Q_UNLIKELY(duration.count() < 0)) { |
165 | qWarning(msg: "QBasicTimer::start: Timers cannot have negative timeouts" ); |
166 | return; |
167 | } |
168 | if (Q_UNLIKELY(!eventDispatcher)) { |
169 | qWarning(msg: "QBasicTimer::start: QBasicTimer can only be used with threads started with QThread" ); |
170 | return; |
171 | } |
172 | if (Q_UNLIKELY(obj && obj->thread() != eventDispatcher->thread())) { |
173 | qWarning(msg: "QBasicTimer::start: Timers cannot be started from another thread" ); |
174 | return; |
175 | } |
176 | stop(); |
177 | if (obj) |
178 | m_id = eventDispatcher->registerTimer(interval: duration, timerType, object: obj); |
179 | } |
180 | |
181 | /*! |
182 | Stops the timer. |
183 | |
184 | \sa start(), isActive() |
185 | */ |
186 | void QBasicTimer::stop() |
187 | { |
188 | if (isActive()) { |
189 | QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance(); |
190 | if (eventDispatcher && !eventDispatcher->unregisterTimer(timerId: m_id)) { |
191 | qWarning(msg: "QBasicTimer::stop: Failed. Possibly trying to stop from a different thread" ); |
192 | return; |
193 | } |
194 | QAbstractEventDispatcherPrivate::releaseTimerId(id: m_id); |
195 | } |
196 | m_id = Qt::TimerId::Invalid; |
197 | } |
198 | |
199 | QT_END_NAMESPACE |
200 | |