QSingleShotTimer: port to chrono

Use std::chrono::ceil<milliseconds> to match what
QDeadlineTimer::remainingTime() did.

Drive-by change: make a method private instead of protected, nothing
inherits from this class anyway

Change-Id: I605b7c25ea7501ee92518ec9f0ff049ed810bfb4
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Ahmad Samir 2023-07-08 18:52:24 +03:00
parent b13c46d6ef
commit 9e1210752f
2 changed files with 32 additions and 23 deletions

View File

@ -20,6 +20,8 @@
#include "qcoreapplication.h" #include "qcoreapplication.h"
#include "qmetaobject_p.h" #include "qmetaobject_p.h"
#include <chrono>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QSingleShotTimer : public QObject class QSingleShotTimer : public QObject
@ -29,31 +31,31 @@ class QSingleShotTimer : public QObject
public: public:
inline ~QSingleShotTimer(); inline ~QSingleShotTimer();
inline QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, inline QSingleShotTimer(std::chrono::milliseconds msec, Qt::TimerType timerType, const QObject *r,
const char *member); const char *member);
inline QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, inline QSingleShotTimer(std::chrono::milliseconds msec, Qt::TimerType timerType, const QObject *r,
QtPrivate::QSlotObjectBase *slotObj); QtPrivate::QSlotObjectBase *slotObj);
inline void startTimerForReceiver(int msec, Qt::TimerType timerType, const QObject *receiver); inline void startTimerForReceiver(std::chrono::milliseconds msec, Qt::TimerType timerType,
const QObject *receiver);
Q_SIGNALS: Q_SIGNALS:
void timeout(); void timeout();
protected: private:
inline void timerEvent(QTimerEvent *) override; inline void timerEvent(QTimerEvent *) override;
}; };
QSingleShotTimer::QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, QSingleShotTimer::QSingleShotTimer(std::chrono::milliseconds msec, Qt::TimerType timerType,
const char *member) const QObject *r, const char *member)
: QObject(QAbstractEventDispatcher::instance()) : QObject(QAbstractEventDispatcher::instance())
{ {
connect(this, SIGNAL(timeout()), r, member); connect(this, SIGNAL(timeout()), r, member);
startTimerForReceiver(msec, timerType, r); startTimerForReceiver(msec, timerType, r);
} }
QSingleShotTimer::QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, QSingleShotTimer::QSingleShotTimer(std::chrono::milliseconds msec, Qt::TimerType timerType,
QtPrivate::QSlotObjectBase *slotObj) const QObject *r, QtPrivate::QSlotObjectBase *slotObj)
: QObject(QAbstractEventDispatcher::instance()) : QObject(QAbstractEventDispatcher::instance())
{ {
int signal_index = QMetaObjectPrivate::signalOffset(&staticMetaObject); int signal_index = QMetaObjectPrivate::signalOffset(&staticMetaObject);
@ -75,8 +77,8 @@ QSingleShotTimer::~QSingleShotTimer()
the same thread as where it will be handled, so that it fires reliably even the same thread as where it will be handled, so that it fires reliably even
if the thread that set up the timer is busy. if the thread that set up the timer is busy.
*/ */
void QSingleShotTimer::startTimerForReceiver(int msec, Qt::TimerType timerType, void QSingleShotTimer::startTimerForReceiver(std::chrono::milliseconds msec,
const QObject *receiver) Qt::TimerType timerType, const QObject *receiver)
{ {
if (receiver && receiver->thread() != thread()) { if (receiver && receiver->thread() != thread()) {
// Avoid leaking the QSingleShotTimer instance in case the application exits before the // Avoid leaking the QSingleShotTimer instance in case the application exits before the
@ -86,15 +88,20 @@ void QSingleShotTimer::startTimerForReceiver(int msec, Qt::TimerType timerType,
setParent(nullptr); setParent(nullptr);
moveToThread(receiver->thread()); moveToThread(receiver->thread());
QDeadlineTimer deadline(std::chrono::milliseconds{msec}, timerType); QDeadlineTimer deadline(msec, timerType);
QMetaObject::invokeMethod(this, [this, deadline, timerType] { auto invokable = [this, deadline, timerType] {
if (deadline.hasExpired()) if (deadline.hasExpired()) {
emit timeout(); Q_EMIT timeout();
else } else {
timerId = startTimer(std::chrono::milliseconds{deadline.remainingTime()}, timerType); auto nsecs = deadline.remainingTimeAsDuration();
}, Qt::QueuedConnection); // Use std::chrono::ceil<milliseconds> to match what
// QDeadlineTimer::remainingTime() did
timerId = startTimer(std::chrono::ceil<std::chrono::milliseconds>(nsecs), timerType);
}
};
QMetaObject::invokeMethod(this, invokable, Qt::QueuedConnection);
} else { } else {
timerId = startTimer(std::chrono::milliseconds{msec}, timerType); timerId = startTimer(msec, timerType);
} }
} }
@ -106,7 +113,7 @@ void QSingleShotTimer::timerEvent(QTimerEvent *)
killTimer(timerId); killTimer(timerId);
timerId = -1; timerId = -1;
emit timeout(); Q_EMIT timeout();
// we would like to use delete later here, but it feels like a // we would like to use delete later here, but it feels like a
// waste to post a new event to handle this event, so we just unset the flag // waste to post a new event to handle this event, so we just unset the flag
@ -116,4 +123,4 @@ void QSingleShotTimer::timerEvent(QTimerEvent *)
QT_END_NAMESPACE QT_END_NAMESPACE
#endif // qsingleshottimer_p.h #endif // QSINGLESHOTTIMER_P_H

View File

@ -15,6 +15,8 @@
#include "qproperty_p.h" #include "qproperty_p.h"
#include "qthread.h" #include "qthread.h"
using namespace std::chrono_literals;
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
/*! /*!
@ -299,7 +301,7 @@ void QTimer::singleShotImpl(int msec, Qt::TimerType timerType,
return; return;
} }
new QSingleShotTimer(msec, timerType, receiver, slotObj); new QSingleShotTimer(msec * 1ms, timerType, receiver, slotObj);
} }
/*! /*!
@ -364,7 +366,7 @@ void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *receiv
Qt::QueuedConnection); Qt::QueuedConnection);
return; return;
} }
(void) new QSingleShotTimer(msec, timerType, receiver, member); (void) new QSingleShotTimer(msec * 1ms, timerType, receiver, member);
} }
} }