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 <thiago.macieira@intel.com>
bb10
Ahmad Samir 2023-03-06 15:02:44 +02:00
parent 957ed5e71e
commit e426a4e3fa
10 changed files with 62 additions and 73 deletions

View File

@ -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.

View File

@ -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<typename T>

View File

@ -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
}

View File

@ -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;

View File

@ -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;

View File

@ -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<int>(fast_timeout.count()));
if (timer_id != -1)
killTimer(timer_id);

View File

@ -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)

View File

@ -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) {

View File

@ -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:

View File

@ -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<xcb_atom_t> drag_types;