From e426a4e3fad376aecdfb1e308b22eba9002aacf7 Mon Sep 17 00:00:00 2001 From: Ahmad Samir Date: Mon, 6 Mar 2023 15:02:44 +0200 Subject: [PATCH] QObject: implement startTimer(int) in terms of startTimer(chrono) I.e. use chrono first, this means the API isn't limited by the size of int, but by the size of whatever chrono::milliseconds uses (typically int64_t), and chrono units are much more readable as well. Task-number: QTBUG-110059 Change-Id: Ie7f2d90864782361a89866693011803be6f8545e Reviewed-by: Thiago Macieira --- src/corelib/kernel/qobject.cpp | 90 +++++++++------------ src/corelib/kernel/qobject.h | 6 +- src/corelib/kernel/qtimer.cpp | 8 +- src/dbus/qdbusintegrator.cpp | 2 +- src/gui/image/qpixmapcache.cpp | 5 +- src/gui/text/qfont.cpp | 12 +-- src/network/socket/qsocks5socketengine.cpp | 4 +- src/plugins/platforms/xcb/qxcbclipboard.cpp | 4 +- src/plugins/platforms/xcb/qxcbdrag.cpp | 2 +- src/plugins/platforms/xcb/qxcbdrag.h | 2 +- 10 files changed, 62 insertions(+), 73 deletions(-) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 34c9e52f63..d3dead9d8f 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1777,74 +1777,33 @@ void QObjectPrivate::_q_reregisterTimers(void *pointer) // /*! - Starts a timer and returns a timer identifier, or returns zero if - it could not start a timer. + \fn int QObject::startTimer(int interval, Qt::TimerType timerType) - A timer event will occur every \a interval milliseconds until - killTimer() is called. If \a interval is 0, then the timer event - occurs once every time there are no more window system events to - process. - - The virtual timerEvent() function is called with the QTimerEvent - event parameter class when a timer event occurs. Reimplement this - function to get timer events. - - If multiple timers are running, the QTimerEvent::timerId() can be - used to find out which timer was activated. - - Example: - - \snippet code/src_corelib_kernel_qobject.cpp 8 - - Note that QTimer's accuracy depends on the underlying operating system and - hardware. The \a timerType argument allows you to customize the accuracy of - the timer. See Qt::TimerType for information on the different timer types. - Most platforms support an accuracy of 20 milliseconds; some provide more. - If Qt is unable to deliver the requested number of timer events, it will - silently discard some. - - The QTimer class provides a high-level programming interface with - single-shot timers and timer signals instead of events. There is - also a QBasicTimer class that is more lightweight than QTimer and - less clumsy than using timer IDs directly. + This is an overloaded function that will start a timer of type + \a timerType and a timeout of \a interval milliseconds. This is + equivalent to calling: + \code + startTimer(std::chrono::milliseconds{interval}, timerType); + \endcode \sa timerEvent(), killTimer(), QTimer::singleShot() */ int QObject::startTimer(int interval, Qt::TimerType timerType) { - Q_D(QObject); - - if (Q_UNLIKELY(interval < 0)) { - qWarning("QObject::startTimer: Timers cannot have negative intervals"); - return 0; - } - - auto thisThreadData = d->threadData.loadRelaxed(); - if (Q_UNLIKELY(!thisThreadData->hasEventDispatcher())) { - qWarning("QObject::startTimer: Timers can only be used with threads started with QThread"); - return 0; - } - if (Q_UNLIKELY(thread() != QThread::currentThread())) { - qWarning("QObject::startTimer: Timers cannot be started from another thread"); - return 0; - } - int timerId = thisThreadData->eventDispatcher.loadRelaxed()->registerTimer(interval, timerType, this); - d->ensureExtraData(); - d->extraData->runningTimers.append(timerId); - return timerId; + return startTimer(std::chrono::milliseconds{interval}, timerType); } /*! \since 5.9 \overload - \fn int QObject::startTimer(std::chrono::milliseconds time, Qt::TimerType timerType) + \fn int QObject::startTimer(std::chrono::milliseconds interval, Qt::TimerType timerType) Starts a timer and returns a timer identifier, or returns zero if it could not start a timer. - A timer event will occur every \a time interval until killTimer() - is called. If \a time is equal to \c{std::chrono::duration::zero()}, + A timer event will occur every \a interval until killTimer() + is called. If \a interval is equal to \c{std::chrono::duration::zero()}, then the timer event occurs once every time there are no more window system events to process. @@ -1873,6 +1832,33 @@ int QObject::startTimer(int interval, Qt::TimerType timerType) \sa timerEvent(), killTimer(), QTimer::singleShot() */ +int QObject::startTimer(std::chrono::milliseconds interval, Qt::TimerType timerType) +{ + Q_D(QObject); + + using namespace std::chrono_literals; + + if (Q_UNLIKELY(interval < 0ms)) { + qWarning("QObject::startTimer: Timers cannot have negative intervals"); + return 0; + } + + auto thisThreadData = d->threadData.loadRelaxed(); + if (Q_UNLIKELY(!thisThreadData->hasEventDispatcher())) { + qWarning("QObject::startTimer: Timers can only be used with threads started with QThread"); + return 0; + } + if (Q_UNLIKELY(thread() != QThread::currentThread())) { + qWarning("QObject::startTimer: Timers cannot be started from another thread"); + return 0; + } + + auto dispatcher = thisThreadData->eventDispatcher.loadRelaxed(); + int timerId = dispatcher->registerTimer(interval.count(), timerType, this); + d->ensureExtraData(); + d->extraData->runningTimers.append(timerId); + return timerId; +} /*! Kills the timer with timer identifier, \a id. diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 075529571f..7f3720df1f 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -126,11 +126,7 @@ public: void moveToThread(QThread *thread); int startTimer(int interval, Qt::TimerType timerType = Qt::CoarseTimer); - Q_ALWAYS_INLINE - int startTimer(std::chrono::milliseconds time, Qt::TimerType timerType = Qt::CoarseTimer) - { - return startTimer(int(time.count()), timerType); - } + int startTimer(std::chrono::milliseconds time, Qt::TimerType timerType = Qt::CoarseTimer); void killTimer(int id); template diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp index b2b9c5f200..73f0fb8fee 100644 --- a/src/corelib/kernel/qtimer.cpp +++ b/src/corelib/kernel/qtimer.cpp @@ -187,7 +187,7 @@ void QTimer::start() Q_D(QTimer); if (d->id != QTimerPrivate::INV_TIMER) // stop running timer stop(); - d->id = QObject::startTimer(d->inter, d->type); + d->id = QObject::startTimer(std::chrono::milliseconds{d->inter}, d->type); d->isActiveData.notify(); } @@ -266,14 +266,14 @@ protected: QSingleShotTimer::QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, const char *member) : QObject(QAbstractEventDispatcher::instance()), hasValidReceiver(true), slotObj(nullptr) { - timerId = startTimer(msec, timerType); + timerId = startTimer(std::chrono::milliseconds{msec}, timerType); connect(this, SIGNAL(timeout()), r, member); } QSingleShotTimer::QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, QtPrivate::QSlotObjectBase *slotObj) : QObject(QAbstractEventDispatcher::instance()), hasValidReceiver(r), receiver(r), slotObj(slotObj) { - timerId = startTimer(msec, timerType); + timerId = startTimer(std::chrono::milliseconds{msec}, timerType); if (r && thread() != r->thread()) { // Avoid leaking the QSingleShotTimer instance in case the application exits before the timer fires connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, &QObject::deleteLater); @@ -708,7 +708,7 @@ void QTimer::setInterval(int msec) d->inter.setValue(msec); if (d->id != QTimerPrivate::INV_TIMER) { // create new timer QObject::killTimer(d->id); // restart timer - d->id = QObject::startTimer(msec, d->type); + d->id = QObject::startTimer(std::chrono::milliseconds{msec}, d->type); // No need to call markDirty() for d->isActiveData here, // as timer state actually does not change } diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 78b87c25c1..28fb32c531 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -124,7 +124,7 @@ static dbus_bool_t qDBusAddTimeout(DBusTimeout *timeout, void *data) Q_ASSERT(d->timeouts.key(timeout, 0) == 0); - int timerId = d->startTimer(q_dbus_timeout_get_interval(timeout)); + int timerId = d->startTimer(std::chrono::milliseconds{q_dbus_timeout_get_interval(timeout)}); Q_ASSERT_X(timerId, "QDBusConnection", "Failed to start a timer"); if (!timerId) return false; diff --git a/src/gui/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp index c16bc359b9..016cd1a987 100644 --- a/src/gui/image/qpixmapcache.cpp +++ b/src/gui/image/qpixmapcache.cpp @@ -8,6 +8,8 @@ #include "qthread.h" #include "qcoreapplication.h" +using namespace std::chrono_literals; + QT_BEGIN_NAMESPACE /*! @@ -202,7 +204,8 @@ public: bool flushDetachedPixmaps(bool nt); private: - enum { soon_time = 10000, flush_time = 30000 }; + static constexpr auto soon_time = 10s; + static constexpr auto flush_time = 30s; int *keyArray; int theid; int ps; diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index 75eb3ff215..1efe3c06d8 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -2796,13 +2796,15 @@ bool QFontInfo::exactMatch() const // QFontCache // ********************************************************************** +using namespace std::chrono_literals; + #ifdef QFONTCACHE_DEBUG // fast timeouts for debugging -static const int fast_timeout = 1000; // 1s -static const int slow_timeout = 5000; // 5s +static constexpr auto fast_timeout = 1s; +static constexpr auto slow_timeout = 5s; #else -static const int fast_timeout = 10000; // 10s -static const int slow_timeout = 300000; // 5m +static constexpr auto fast_timeout = 10s; +static constexpr auto slow_timeout = 5min; #endif // QFONTCACHE_DEBUG #ifndef QFONTCACHE_MIN_COST @@ -3012,7 +3014,7 @@ void QFontCache::increaseCost(uint cost) return; if (timer_id == -1 || ! fast) { - FC_DEBUG(" TIMER: starting fast timer (%d ms)", fast_timeout); + FC_DEBUG(" TIMER: starting fast timer (%d s)", static_cast(fast_timeout.count())); if (timer_id != -1) killTimer(timer_id); diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp index b1bca2bf4d..2669614f3a 100644 --- a/src/network/socket/qsocks5socketengine.cpp +++ b/src/network/socket/qsocks5socketengine.cpp @@ -317,9 +317,11 @@ void QSocks5BindStore::add(qintptr socketDescriptor, QSocks5BindData *bindData) } bindData->timeStamp.start(); store.insert(socketDescriptor, bindData); + + using namespace std::chrono_literals; // start sweep timer if not started if (sweepTimerId == -1) - sweepTimerId = startTimer(60000); + sweepTimerId = startTimer(1min); } bool QSocks5BindStore::contains(qintptr socketDescriptor) diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index 0de0db2a58..40e2f47354 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -126,7 +126,7 @@ QXcbClipboardTransaction::QXcbClipboardTransaction(QXcbClipboard *clipboard, xcb xcb_change_window_attributes(m_clipboard->xcb_connection(), m_window, XCB_CW_EVENT_MASK, values); - m_abortTimerId = startTimer(m_clipboard->clipboardTimeout()); + m_abortTimerId = startTimer(std::chrono::milliseconds{m_clipboard->clipboardTimeout()}); } QXcbClipboardTransaction::~QXcbClipboardTransaction() @@ -145,7 +145,7 @@ bool QXcbClipboardTransaction::updateIncrementalProperty(const xcb_property_noti // restart the timer if (m_abortTimerId) killTimer(m_abortTimerId); - m_abortTimerId = startTimer(m_clipboard->clipboardTimeout()); + m_abortTimerId = startTimer(std::chrono::milliseconds{m_clipboard->clipboardTimeout()}); uint bytes_left = uint(m_data.size()) - m_offset; if (bytes_left > 0) { diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index e209277144..3ef37e85c5 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -1097,7 +1097,7 @@ void QXcbDrag::timerEvent(QTimerEvent* e) continue; } QTime currentTime = QTime::currentTime(); - int delta = t.time.msecsTo(currentTime); + std::chrono::milliseconds delta{t.time.msecsTo(currentTime)}; if (delta > XdndDropTransactionTimeout) { /* delete transactions which are older than XdndDropTransactionTimeout. It could mean one of these: diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h index 5f49b0fd57..ae7cc915c8 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.h +++ b/src/plugins/platforms/xcb/qxcbdrag.h @@ -127,7 +127,7 @@ private: QXcbVirtualDesktop *current_virtual_desktop; // 10 minute timer used to discard old XdndDrop transactions - enum { XdndDropTransactionTimeout = 600000 }; + static constexpr std::chrono::minutes XdndDropTransactionTimeout{10}; int cleanup_timer; QList drag_types;