Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qtimer.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 "qtimer.h"
6#include "qtimer_p.h"
7
9#include "qcoreapplication.h"
10#include "qcoreapplication_p.h"
11#include "qdeadlinetimer.h"
12#include "qmetaobject_p.h"
13#include "qobject_p.h"
14#include "qproperty_p.h"
15#include "qthread.h"
16
18
119{
120}
121
122
128{
129 if (d_func()->id != QTimerPrivate::INV_TIMER) // stop running timer
130 stop();
131}
132
133
157{
158 return d_func()->isActiveData.value();
159}
160
162{
163 return QBindable<bool>(&d_func()->isActiveData);
164}
165
173{
174 return d_func()->id;
175}
176
177
188{
189 Q_D(QTimer);
190 if (d->id != QTimerPrivate::INV_TIMER) // stop running timer
191 stop();
192 d->id = QObject::startTimer(std::chrono::milliseconds{d->inter}, d->type);
193 d->isActiveData.notify();
194}
195
208void QTimer::start(int msec)
209{
210 Q_D(QTimer);
211 const bool intervalChanged = msec != d->inter;
212 d->inter.setValue(msec);
213 start();
214 if (intervalChanged)
215 d->inter.notify();
216}
217
218
219
227{
228 Q_D(QTimer);
229 if (d->id != QTimerPrivate::INV_TIMER) {
232 d->isActiveData.notify();
233 }
234}
235
236
241{
242 Q_D(QTimer);
243 if (e->timerId() == d->id) {
244 if (d->single)
245 stop();
246 emit timeout(QPrivateSignal());
247 }
248}
249
251{
253 int timerId = -1;
254public:
256 QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, const char * m);
257 QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, QtPrivate::QSlotObjectBase *slotObj);
258
259 void startTimerForReceiver(int msec, Qt::TimerType timerType, const QObject *receiver);
260
262 void timeout();
263protected:
264 void timerEvent(QTimerEvent *) override;
265};
266
267QSingleShotTimer::QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, const char *member)
268 : QObject(QAbstractEventDispatcher::instance())
269{
270 connect(this, SIGNAL(timeout()), r, member);
271
272 startTimerForReceiver(msec, timerType, r);
273}
274
276 : QObject(QAbstractEventDispatcher::instance())
277{
278 int signal_index = QMetaObjectPrivate::signalOffset(&staticMetaObject);
279 Q_ASSERT(QMetaObjectPrivate::signal(&staticMetaObject, signal_index).name() == "timeout");
280 QObjectPrivate::connectImpl(this, signal_index, r ? r : this, nullptr, slotObj,
281 Qt::AutoConnection, nullptr, &staticMetaObject);
282
283 startTimerForReceiver(msec, timerType, r);
284}
285
287{
288 if (timerId > 0)
289 killTimer(timerId);
290}
291
292/*
293 Move the timer, and the dispatching and handling of the timer event, into
294 the same thread as where it will be handled, so that it fires reliably even
295 if the thread that set up the timer is busy.
296*/
297void QSingleShotTimer::startTimerForReceiver(int msec, Qt::TimerType timerType, const QObject *receiver)
298{
299 if (receiver && receiver->thread() != thread()) {
300 // Avoid leaking the QSingleShotTimer instance in case the application exits before the timer fires
302 setParent(nullptr);
303 moveToThread(receiver->thread());
304
305 QDeadlineTimer deadline(std::chrono::milliseconds{msec}, timerType);
306 QMetaObject::invokeMethod(this, [this, deadline, timerType]{
307 if (deadline.hasExpired())
308 emit timeout();
309 else
310 timerId = startTimer(std::chrono::milliseconds{deadline.remainingTime()}, timerType);
312 } else {
313 timerId = startTimer(std::chrono::milliseconds{msec}, timerType);
314 }
315}
316
317
319{
320 // need to kill the timer _before_ we emit timeout() in case the
321 // slot connected to timeout calls processEvents()
322 if (timerId > 0)
323 killTimer(timerId);
324 timerId = -1;
325
326 emit timeout();
327
328 // we would like to use delete later here, but it feels like a
329 // waste to post a new event to handle this event, so we just unset the flag
330 // and explicitly delete...
332}
333
346void QTimer::singleShotImpl(int msec, Qt::TimerType timerType,
347 const QObject *receiver,
349{
350 if (msec == 0) {
351 bool deleteReceiver = false;
352 // Optimize: set a receiver context when none is given, such that we can use
353 // QMetaObject::invokeMethod which is more efficient than going through a timer.
354 // We need a QObject living in the current thread. But the QThread itself lives
355 // in a different thread - with the exception of the main QThread which lives in
356 // itself. And QThread::currentThread() is among the few QObjects we know that will
357 // most certainly be there. Note that one can actually call singleShot before the
358 // QApplication is created!
360 // reuse main thread as context object
361 receiver = QThread::currentThread();
362 } else if (!receiver) {
363 // Create a receiver context object on-demand. According to the benchmarks,
364 // this is still more efficient than going through a timer.
365 receiver = new QObject;
366 deleteReceiver = true;
367 }
368
369 QMetaObject::invokeMethodImpl(const_cast<QObject *>(receiver), slotObj,
370 Qt::QueuedConnection, nullptr);
371
372 if (deleteReceiver)
373 const_cast<QObject *>(receiver)->deleteLater();
374 return;
375 }
376
377 new QSingleShotTimer(msec, timerType, receiver, slotObj);
378}
379
400void QTimer::singleShot(int msec, const QObject *receiver, const char *member)
401{
402 // coarse timers are worst in their first firing
403 // so we prefer a high precision timer for something that happens only once
404 // unless the timeout is too big, in which case we go for coarse anyway
405 singleShot(msec, msec >= 2000 ? Qt::CoarseTimer : Qt::PreciseTimer, receiver, member);
406}
407
422void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *receiver, const char *member)
423{
424 if (Q_UNLIKELY(msec < 0)) {
425 qWarning("QTimer::singleShot: Timers cannot have negative timeouts");
426 return;
427 }
428 if (receiver && member) {
429 if (msec == 0) {
430 // special code shortpath for 0-timers
431 const char* bracketPosition = strchr(member, '(');
432 if (!bracketPosition || !(member[0] >= '0' && member[0] <= '2')) {
433 qWarning("QTimer::singleShot: Invalid slot specification");
434 return;
435 }
436 QByteArray methodName(member+1, bracketPosition - 1 - member); // extract method name
438 return;
439 }
440 (void) new QSingleShotTimer(msec, timerType, receiver, member);
441 }
442}
443
580void QTimer::setSingleShot(bool singleShot)
581{
582 d_func()->single = singleShot;
583}
584
586{
587 return d_func()->single;
588}
589
591{
592 return QBindable<bool>(&d_func()->single);
593}
594
608{
609 Q_D(QTimer);
610 const bool intervalChanged = msec != d->inter;
611 d->inter.setValue(msec);
612 if (d->id != QTimerPrivate::INV_TIMER) { // create new timer
613 QObject::killTimer(d->id); // restart timer
614 d->id = QObject::startTimer(std::chrono::milliseconds{msec}, d->type);
615 // No need to call markDirty() for d->isActiveData here,
616 // as timer state actually does not change
617 }
618 if (intervalChanged)
619 d->inter.notify();
620}
621
623{
624 return d_func()->inter;
625}
626
628{
629 return QBindable<int>(&d_func()->inter);
630}
631
644{
645 Q_D(const QTimer);
646 if (d->id != QTimerPrivate::INV_TIMER) {
648 }
649
650 return -1;
651}
652
662{
663 d_func()->type = atype;
664}
665
667{
668 return d_func()->type;
669}
670
672{
673 return QBindable<Qt::TimerType>(&d_func()->type);
674}
675
677
678#include "qtimer.moc"
679#include "moc_qtimer.cpp"
static QAbstractEventDispatcher * instance(QThread *thread=nullptr)
Returns a pointer to the event dispatcher object for the specified thread.
virtual int remainingTime(int timerId)=0
Returns the remaining time in milliseconds with the given timerId.
\inmodule QtCore
Definition qproperty.h:809
\inmodule QtCore
Definition qbytearray.h:57
static QThread * mainThread()
static QCoreApplication * instance() noexcept
Returns a pointer to the application's QCoreApplication (or QGuiApplication/QApplication) instance.
void aboutToQuit(QPrivateSignal)
This signal is emitted when the application is about to quit the main event loop, e....
\inmodule QtCore
bool hasExpired() const noexcept
Returns true if this QDeadlineTimer object has expired, false if there remains time left.
qint64 remainingTime() const noexcept
Returns the remaining time in this QDeadlineTimer object in milliseconds.
static QMetaObject::Connection connectImpl(const QObject *sender, int signal_index, const QObject *receiver, void **slot, QtPrivate::QSlotObjectBase *slotObj, int type, const int *types, const QMetaObject *senderMetaObject)
Definition qobject.cpp:5090
\inmodule QtCore
Definition qobject.h:90
int startTimer(int interval, Qt::TimerType timerType=Qt::CoarseTimer)
This is an overloaded function that will start a timer of type timerType and a timeout of interval mi...
Definition qobject.cpp:1792
void moveToThread(QThread *thread)
Changes the thread affinity for this object and its children.
Definition qobject.cpp:1606
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
void setParent(QObject *parent)
Makes the object a child of parent.
Definition qobject.cpp:2142
QThread * thread() const
Returns the thread in which the object lives.
Definition qobject.cpp:1561
void killTimer(int id)
Kills the timer with timer identifier, id.
Definition qobject.cpp:1872
void deleteLater()
\threadsafe
Definition qobject.cpp:2352
void startTimerForReceiver(int msec, Qt::TimerType timerType, const QObject *receiver)
Definition qtimer.cpp:297
QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, const char *m)
Definition qtimer.cpp:267
void timerEvent(QTimerEvent *) override
This event handler can be reimplemented in a subclass to receive timer events for the object.
Definition qtimer.cpp:318
const QChar * constData() const
Returns a pointer to the data stored in the QString.
Definition qstring.h:1101
static QThread * currentThread()
Definition qthread.cpp:966
\inmodule QtCore
Definition qcoreevent.h:359
static constexpr int INV_TIMER
Definition qtimer_p.h:25
\inmodule QtCore
Definition qtimer.h:20
QTimer(QObject *parent=nullptr)
Constructs a timer with the given parent.
Definition qtimer.cpp:117
void setSingleShot(bool singleShot)
Definition qtimer.cpp:580
void timerEvent(QTimerEvent *) override
\reimp
Definition qtimer.cpp:240
bool isSingleShot() const
Definition qtimer.cpp:585
void start(int msec)
Starts or restarts the timer with a timeout interval of msec milliseconds.
Definition qtimer.cpp:208
int interval
the timeout interval in milliseconds
Definition qtimer.h:23
int remainingTime
the remaining time in milliseconds
Definition qtimer.h:24
Qt::TimerType timerType
controls the accuracy of the timer
Definition qtimer.h:25
void setInterval(int msec)
Definition qtimer.cpp:607
QBindable< Qt::TimerType > bindableTimerType()
Definition qtimer.cpp:671
int timerId() const
Returns the ID of the timer if the timer is running; otherwise returns -1.
Definition qtimer.cpp:172
bool isActive() const
Returns true if the timer is running (pending); otherwise returns false.
Definition qtimer.cpp:156
bool singleShot
whether the timer is a single-shot timer
Definition qtimer.h:22
QBindable< int > bindableInterval()
Definition qtimer.cpp:627
QBindable< bool > bindableActive()
Definition qtimer.cpp:161
void stop()
Stops the timer.
Definition qtimer.cpp:226
void timeout(QPrivateSignal)
This signal is emitted when the timer times out.
QBindable< bool > bindableSingleShot()
Definition qtimer.cpp:590
~QTimer()
Destroys the timer.
Definition qtimer.cpp:127
void setTimerType(Qt::TimerType atype)
Definition qtimer.cpp:661
double e
Combined button and popup list for selecting options.
TimerType
@ CoarseTimer
@ PreciseTimer
@ AutoConnection
@ QueuedConnection
#define Q_UNLIKELY(x)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
static QString methodName(const QDBusIntrospection::Method &method)
#define qWarning
Definition qlogging.h:162
void qDeleteInEventHandler(QObject *o)
Definition qobject.cpp:4876
#define SIGNAL(a)
Definition qobjectdefs.h:52
const GLfloat * m
GLboolean r
[2]
GLbitfield GLuint64 timeout
[4]
GLenum type
GLuint name
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_OBJECT
#define Q_SIGNALS
#define emit
QDeadlineTimer deadline(30s)
static int signalOffset(const QMetaObject *m)
static Q_CORE_EXPORT QMetaMethod signal(const QMetaObject *m, int signal_index)
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent