QTimer: split QSingleShotTimer to a private header
So that it can be used in QTimer and soon-to-added QChronoTimer, this is less code duplication. Change-Id: Icc5f2028d776a34c06ba20fe41f571cd3821c64c Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>bb10
parent
6f1449c7ae
commit
e0573e7364
|
|
@ -181,6 +181,7 @@ qt_internal_add_module(Core
|
|||
kernel/qsocketnotifier.cpp kernel/qsocketnotifier.h
|
||||
kernel/qsystemerror.cpp kernel/qsystemerror_p.h
|
||||
kernel/qtestsupport_core.cpp kernel/qtestsupport_core.h
|
||||
kernel/qsingleshottimer_p.h
|
||||
kernel/qtimer.cpp kernel/qtimer.h kernel/qtimer_p.h
|
||||
kernel/qtranslator.cpp kernel/qtranslator.h kernel/qtranslator_p.h
|
||||
kernel/qvariant.cpp kernel/qvariant.h kernel/qvariant_p.h
|
||||
|
|
|
|||
|
|
@ -0,0 +1,119 @@
|
|||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// Copyright (C) 2016 Intel Corporation.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef QSINGLESHOTTIMER_P_H
|
||||
#define QSINGLESHOTTIMER_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "qabstracteventdispatcher.h"
|
||||
#include "qcoreapplication.h"
|
||||
#include "qmetaobject_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QSingleShotTimer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
int timerId = -1;
|
||||
|
||||
public:
|
||||
inline ~QSingleShotTimer();
|
||||
inline QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r,
|
||||
const char *member);
|
||||
inline QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r,
|
||||
QtPrivate::QSlotObjectBase *slotObj);
|
||||
|
||||
inline void startTimerForReceiver(int msec, Qt::TimerType timerType, const QObject *receiver);
|
||||
|
||||
Q_SIGNALS:
|
||||
void timeout();
|
||||
|
||||
protected:
|
||||
inline void timerEvent(QTimerEvent *) override;
|
||||
};
|
||||
|
||||
QSingleShotTimer::QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r,
|
||||
const char *member)
|
||||
: QObject(QAbstractEventDispatcher::instance())
|
||||
{
|
||||
connect(this, SIGNAL(timeout()), r, member);
|
||||
|
||||
startTimerForReceiver(msec, timerType, r);
|
||||
}
|
||||
|
||||
QSingleShotTimer::QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r,
|
||||
QtPrivate::QSlotObjectBase *slotObj)
|
||||
: QObject(QAbstractEventDispatcher::instance())
|
||||
{
|
||||
int signal_index = QMetaObjectPrivate::signalOffset(&staticMetaObject);
|
||||
Q_ASSERT(QMetaObjectPrivate::signal(&staticMetaObject, signal_index).name() == "timeout");
|
||||
QObjectPrivate::connectImpl(this, signal_index, r ? r : this, nullptr, slotObj,
|
||||
Qt::AutoConnection, nullptr, &staticMetaObject);
|
||||
|
||||
startTimerForReceiver(msec, timerType, r);
|
||||
}
|
||||
|
||||
QSingleShotTimer::~QSingleShotTimer()
|
||||
{
|
||||
if (timerId > 0)
|
||||
killTimer(timerId);
|
||||
}
|
||||
|
||||
/*
|
||||
Move the timer, and the dispatching and handling of the timer event, into
|
||||
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.
|
||||
*/
|
||||
void QSingleShotTimer::startTimerForReceiver(int msec, Qt::TimerType timerType,
|
||||
const QObject *receiver)
|
||||
{
|
||||
if (receiver && receiver->thread() != thread()) {
|
||||
// Avoid leaking the QSingleShotTimer instance in case the application exits before the
|
||||
// timer fires
|
||||
connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this,
|
||||
&QObject::deleteLater);
|
||||
setParent(nullptr);
|
||||
moveToThread(receiver->thread());
|
||||
|
||||
QDeadlineTimer deadline(std::chrono::milliseconds{msec}, timerType);
|
||||
QMetaObject::invokeMethod(this, [this, deadline, timerType] {
|
||||
if (deadline.hasExpired())
|
||||
emit timeout();
|
||||
else
|
||||
timerId = startTimer(std::chrono::milliseconds{deadline.remainingTime()}, timerType);
|
||||
}, Qt::QueuedConnection);
|
||||
} else {
|
||||
timerId = startTimer(std::chrono::milliseconds{msec}, timerType);
|
||||
}
|
||||
}
|
||||
|
||||
void QSingleShotTimer::timerEvent(QTimerEvent *)
|
||||
{
|
||||
// need to kill the timer _before_ we emit timeout() in case the
|
||||
// slot connected to timeout calls processEvents()
|
||||
if (timerId > 0)
|
||||
killTimer(timerId);
|
||||
timerId = -1;
|
||||
|
||||
emit timeout();
|
||||
|
||||
// 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
|
||||
// and explicitly delete...
|
||||
qDeleteInEventHandler(this);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // qsingleshottimer_p.h
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "qtimer.h"
|
||||
#include "qtimer_p.h"
|
||||
#include "qsingleshottimer_p.h"
|
||||
|
||||
#include "qabstracteventdispatcher.h"
|
||||
#include "qcoreapplication.h"
|
||||
|
|
@ -253,90 +254,6 @@ void QTimer::timerEvent(QTimerEvent *e)
|
|||
}
|
||||
}
|
||||
|
||||
class QSingleShotTimer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
int timerId = -1;
|
||||
public:
|
||||
~QSingleShotTimer();
|
||||
QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, const char * m);
|
||||
QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, QtPrivate::QSlotObjectBase *slotObj);
|
||||
|
||||
void startTimerForReceiver(int msec, Qt::TimerType timerType, const QObject *receiver);
|
||||
|
||||
Q_SIGNALS:
|
||||
void timeout();
|
||||
protected:
|
||||
void timerEvent(QTimerEvent *) override;
|
||||
};
|
||||
|
||||
QSingleShotTimer::QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, const char *member)
|
||||
: QObject(QAbstractEventDispatcher::instance())
|
||||
{
|
||||
connect(this, SIGNAL(timeout()), r, member);
|
||||
|
||||
startTimerForReceiver(msec, timerType, r);
|
||||
}
|
||||
|
||||
QSingleShotTimer::QSingleShotTimer(int msec, Qt::TimerType timerType, const QObject *r, QtPrivate::QSlotObjectBase *slotObj)
|
||||
: QObject(QAbstractEventDispatcher::instance())
|
||||
{
|
||||
int signal_index = QMetaObjectPrivate::signalOffset(&staticMetaObject);
|
||||
Q_ASSERT(QMetaObjectPrivate::signal(&staticMetaObject, signal_index).name() == "timeout");
|
||||
QObjectPrivate::connectImpl(this, signal_index, r ? r : this, nullptr, slotObj,
|
||||
Qt::AutoConnection, nullptr, &staticMetaObject);
|
||||
|
||||
startTimerForReceiver(msec, timerType, r);
|
||||
}
|
||||
|
||||
QSingleShotTimer::~QSingleShotTimer()
|
||||
{
|
||||
if (timerId > 0)
|
||||
killTimer(timerId);
|
||||
}
|
||||
|
||||
/*
|
||||
Move the timer, and the dispatching and handling of the timer event, into
|
||||
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.
|
||||
*/
|
||||
void QSingleShotTimer::startTimerForReceiver(int msec, Qt::TimerType timerType, const QObject *receiver)
|
||||
{
|
||||
if (receiver && receiver->thread() != thread()) {
|
||||
// Avoid leaking the QSingleShotTimer instance in case the application exits before the timer fires
|
||||
connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, &QObject::deleteLater);
|
||||
setParent(nullptr);
|
||||
moveToThread(receiver->thread());
|
||||
|
||||
QDeadlineTimer deadline(std::chrono::milliseconds{msec}, timerType);
|
||||
QMetaObject::invokeMethod(this, [this, deadline, timerType]{
|
||||
if (deadline.hasExpired())
|
||||
emit timeout();
|
||||
else
|
||||
timerId = startTimer(std::chrono::milliseconds{deadline.remainingTime()}, timerType);
|
||||
}, Qt::QueuedConnection);
|
||||
} else {
|
||||
timerId = startTimer(std::chrono::milliseconds{msec}, timerType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void QSingleShotTimer::timerEvent(QTimerEvent *)
|
||||
{
|
||||
// need to kill the timer _before_ we emit timeout() in case the
|
||||
// slot connected to timeout calls processEvents()
|
||||
if (timerId > 0)
|
||||
killTimer(timerId);
|
||||
timerId = -1;
|
||||
|
||||
emit timeout();
|
||||
|
||||
// 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
|
||||
// and explicitly delete...
|
||||
qDeleteInEventHandler(this);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
|
|
@ -699,5 +616,4 @@ QBindable<Qt::TimerType> QTimer::bindableTimerType()
|
|||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#include "qtimer.moc"
|
||||
#include "moc_qtimer.cpp"
|
||||
|
|
|
|||
Loading…
Reference in New Issue