Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qchronotimer.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 "qchronotimer.h"
6#include "qtimer_p.h"
8
10#include "qcoreapplication.h"
11#include "qcoreapplication_p.h"
12#include "qdeadlinetimer.h"
13#include "qmetaobject_p.h"
14#include "qobject_p.h"
15#include "qproperty_p.h"
16#include "qthread.h"
17
18using namespace std::chrono_literals;
19
21
118 : QChronoTimer(0ns, parent)
119{
120}
121
125QChronoTimer::QChronoTimer(std::chrono::nanoseconds nsec, QObject *parent)
126 : QObject(*new QTimerPrivate(nsec, this), parent)
127{
128 Q_ASSERT(!d_func()->isQTimer);
129}
130
135{
136 if (d_func()->isActive()) // stop running timer
137 stop();
138}
139
160{
161 return d_func()->isActiveData.value();
162}
163
165{
166 return QBindable<bool>(&d_func()->isActiveData);
167}
168
176{
177 return d_func()->id;
178}
179
190{
191 auto *d = d_func();
192 if (d->isActive()) // stop running timer
193 stop();
194 const auto id = Qt::TimerId{QObject::startTimer(d->intervalDuration, d->type)};
195 if (id > Qt::TimerId::Invalid) {
196 d->id = id;
197 d->isActiveData.notify();
198 }
199}
200
207{
208 auto *d = d_func();
209 if (d->isActive()) {
212 d->isActiveData.notify();
213 }
214}
215
220{
221 auto *d = d_func();
222 if (Qt::TimerId{e->timerId()} == d->id) {
223 if (d->single)
224 stop();
225 Q_EMIT timeout(QPrivateSignal());
226 }
227}
228
256void QChronoTimer::setSingleShot(bool singleShot)
257{
258 d_func()->single = singleShot;
259}
260
262{
263 return d_func()->single;
264}
265
267{
268 return QBindable<bool>(&d_func()->single);
269}
270
285void QChronoTimer::setInterval(std::chrono::nanoseconds nsec)
286{
287 auto *d = d_func();
288 d->intervalDuration.removeBindingUnlessInWrapper();
289 const bool intervalChanged = nsec != d->intervalDuration.valueBypassingBindings();
290 d->intervalDuration.setValueBypassingBindings(nsec);
291 if (d->isActive()) { // Create new timer
292 QObject::killTimer(d->id); // Restart timer
293 const auto newId = Qt::TimerId{QObject::startTimer(nsec, d->type)};
294 if (newId > Qt::TimerId::Invalid) {
295 // Restarted successfully. No need to update the active state.
296 d->id = newId;
297 } else {
298 // Failed to start the timer.
299 // Need to notify about active state change.
301 d->isActiveData.notify();
302 }
303 }
304 if (intervalChanged)
305 d->intervalDuration.notify();
306}
307
308std::chrono::nanoseconds QChronoTimer::interval() const
309{
310 return d_func()->intervalDuration.value();
311}
312
313QBindable<std::chrono::nanoseconds> QChronoTimer::bindableInterval()
314{
315 return {&d_func()->intervalDuration};
316}
317
330std::chrono::nanoseconds QChronoTimer::remainingTime() const
331{
332 if (isActive())
333 return QAbstractEventDispatcher::instance()->remainingTime(d_func()->id);
334 return std::chrono::nanoseconds::min();
335}
336
346{
347 d_func()->type = atype;
348}
349
351{
352 return d_func()->type;
353}
354
355QBindable<Qt::TimerType> QChronoTimer::bindableTimerType()
356{
357 return {&d_func()->type};
358}
359
376void QChronoTimer::singleShot(std::chrono::nanoseconds interval, Qt::TimerType timerType,
377 const QObject *receiver, const char *member)
378{
379 if (Q_UNLIKELY(interval < 0ns)) {
380 qWarning("QChronoTimer::singleShot: Timers cannot have negative timeouts");
381 return;
382 }
383 if (receiver && member) {
384 if (interval == 0ns) {
385 // special code shortpath for 0-timers
386 const char* bracketPosition = strchr(member, '(');
387 if (!bracketPosition || !(member[0] >= '0' && member[0] <= '2')) {
388 qWarning("QChronoTimer::singleShot: Invalid slot specification");
389 return;
390 }
391 const auto methodName = QByteArrayView(member + 1, // extract method name
392 bracketPosition - 1 - member).trimmed();
393 QMetaObject::invokeMethod(const_cast<QObject *>(receiver),
394 methodName.toByteArray().constData(),
396 return;
397 }
398 (void) new QSingleShotTimer(interval, timerType, receiver, member);
399 }
400}
401
415void QChronoTimer::singleShotImpl(std::chrono::nanoseconds interval, Qt::TimerType timerType,
416 const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj)
417{
418 if (interval == 0ns) {
419 bool deleteReceiver = false;
420 // Optimize: set a receiver context when none is given, such that we can use
421 // QMetaObject::invokeMethod which is more efficient than going through a timer.
422 // We need a QObject living in the current thread. But the QThread itself lives
423 // in a different thread - with the exception of the main QThread which lives in
424 // itself. And QThread::currentThread() is among the few QObjects we know that will
425 // most certainly be there. Note that one can actually call singleShot before the
426 // QApplication is created!
428 // reuse main thread as context object
429 receiver = QThread::currentThread();
430 } else if (!receiver) {
431 // Create a receiver context object on-demand. According to the benchmarks,
432 // this is still more efficient than going through a timer.
433 receiver = new QObject;
434 deleteReceiver = true;
435 }
436
438 QMetaObject::invokeMethodImpl(const_cast<QObject *>(receiver), slotObj,
439 Qt::QueuedConnection, h.parameterCount(), h.parameters.data(), h.typeNames.data(),
440 h.metaTypes.data());
441
442 if (deleteReceiver)
443 const_cast<QObject *>(receiver)->deleteLater();
444 return;
445 }
446
447 new QSingleShotTimer(interval, timerType, receiver, slotObj);
448}
449
451
452#include "moc_qchronotimer.cpp"
static QAbstractEventDispatcher * instance(QThread *thread=nullptr)
Returns a pointer to the event dispatcher object for the specified thread.
QByteArrayView trimmed() const noexcept
\inmodule QtCore
QBindable< bool > bindableActive()
QChronoTimer(std::chrono::nanoseconds nsec, QObject *parent=nullptr)
Constructs a timer with the given parent, using an interval of nsec.
void setSingleShot(bool singleShot)
QBindable< Qt::TimerType > bindableTimerType()
bool singleShot
Whether the timer is a single-shot timer.
Qt::TimerType timerType
Controls the accuracy of the timer.
Qt::TimerId id() const
Returns a Qt::TimerId representing the timer ID if the timer is running; otherwise returns Qt::TimerI...
void timerEvent(QTimerEvent *) override
\reimp
QBindable< bool > bindableSingleShot()
std::chrono::nanoseconds remainingTime
The remaining time.
void setTimerType(Qt::TimerType atype)
~QChronoTimer() override
Destroys the timer.
void setInterval(std::chrono::nanoseconds nsec)
QBindable< std::chrono::nanoseconds > bindableInterval()
std::chrono::nanoseconds interval
The timeout interval.
bool isActive() const
Returns true if the timer is running (pending); otherwise returns false.
void stop()
Stops the timer.
bool isSingleShot() const
static QThread * mainThread()
\inmodule QtCore
Definition qobject.h:103
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:1817
Q_INVOKABLE QObject(QObject *parent=nullptr)
Constructs an object with parent object parent.
Definition qobject.cpp:936
void killTimer(int id)
Kills the timer with timer identifier, id.
Definition qobject.cpp:1912
void deleteLater()
\threadsafe
Definition qobject.cpp:2435
static QThread * currentThread()
Definition qthread.cpp:1039
\inmodule QtCore
Definition qcoreevent.h:366
int timerId() const
Returns the unique timer identifier, which is the same identifier as returned from QObject::startTime...
Definition qcoreevent.h:370
Qt::TimerId id
Definition qtimer_p.h:59
#define this
Definition dialogs.cpp:9
Combined button and popup list for selecting options.
auto invokeMethodHelper(QMetaMethodReturnArgument r, const Args &... arguments)
TimerType
@ 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:166
GLbitfield GLuint64 timeout
[4]
GLfloat GLfloat GLfloat GLfloat h
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_EMIT
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...