QSingleShotTimer: de-inline [1/4]: add .cpp file

... and split code between header and .cpp file. The goal here is to
just sort the lines into header and .cpp, not to change them, so
temporarily define inline away. This allows git to reliably track
this as copy instead of independent changes. The inline define will be
cleaned up in a follow-up patch; fixing inline and re-indenting would
reduce the similarity score too much.

Also includemocs and move qsingleshottimer* to the (lexicographically)
correct position in CMakeLists.txt's SOURCES.

Fixes -Wweak-vtable (and therefore prevents this class from being used
outside QtCore (not exported atm)).

Amends e0573e73645c0f57e46332a94160e28eb6c8ebac.

Change-Id: Ia5304434fd1c9a56eb6f2f1988bd14a80ab61442
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit 1ef5f50e28edd1bdfcb3828c3858640ba347b2bd)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Marc Mutz 2024-06-28 10:18:20 +02:00 committed by Qt Cherry-pick Bot
parent 678c839575
commit e3da82d3b6
3 changed files with 92 additions and 72 deletions

View File

@ -176,10 +176,10 @@ qt_internal_add_module(Core
kernel/qpropertyprivate.h
kernel/qsequentialiterable.cpp kernel/qsequentialiterable.h
kernel/qsignalmapper.cpp kernel/qsignalmapper.h
kernel/qsingleshottimer.cpp kernel/qsingleshottimer_p.h
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

View File

@ -0,0 +1,89 @@
// 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
#include <QtCore/private/qsingleshottimer_p.h>
#include "qabstracteventdispatcher.h"
#include "qcoreapplication.h"
#include "qmetaobject_p.h"
#include "private/qnumeric_p.h"
#include <chrono>
QT_BEGIN_NAMESPACE
QSingleShotTimer::QSingleShotTimer(Duration interval, Qt::TimerType timerType,
const QObject *r, const char *member)
: QObject(QAbstractEventDispatcher::instance())
{
connect(this, SIGNAL(timeout()), r, member);
startTimerForReceiver(interval, timerType, r);
}
QSingleShotTimer::QSingleShotTimer(Duration interval, 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(interval, timerType, r);
}
QSingleShotTimer::~QSingleShotTimer()
{
if (timerId > Qt::TimerId::Invalid)
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(Duration interval, 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(interval, timerType);
auto invokable = [this, deadline, timerType] {
if (deadline.hasExpired()) {
Q_EMIT timeout();
} else {
timerId = Qt::TimerId{startTimer(deadline.remainingTimeAsDuration(), timerType)};
}
};
QMetaObject::invokeMethod(this, invokable, Qt::QueuedConnection);
} else {
timerId = Qt::TimerId{startTimer(interval, 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 > Qt::TimerId::Invalid)
killTimer(std::exchange(timerId, Qt::TimerId::Invalid));
Q_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...
delete this;
}
QT_END_NAMESPACE
#include "moc_qsingleshottimer_p.cpp"

View File

@ -31,6 +31,7 @@ class QSingleShotTimer : public QObject
Qt::TimerId timerId = Qt::TimerId::Invalid;
#define inline
public:
// use the same duration type
using Duration = QAbstractEventDispatcher::Duration;
@ -63,79 +64,9 @@ Q_SIGNALS:
private:
inline void timerEvent(QTimerEvent *) override;
#undef inline
};
QSingleShotTimer::QSingleShotTimer(Duration interval, Qt::TimerType timerType,
const QObject *r, const char *member)
: QObject(QAbstractEventDispatcher::instance())
{
connect(this, SIGNAL(timeout()), r, member);
startTimerForReceiver(interval, timerType, r);
}
QSingleShotTimer::QSingleShotTimer(Duration interval, 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(interval, timerType, r);
}
QSingleShotTimer::~QSingleShotTimer()
{
if (timerId > Qt::TimerId::Invalid)
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(Duration interval, 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(interval, timerType);
auto invokable = [this, deadline, timerType] {
if (deadline.hasExpired()) {
Q_EMIT timeout();
} else {
timerId = Qt::TimerId{startTimer(deadline.remainingTimeAsDuration(), timerType)};
}
};
QMetaObject::invokeMethod(this, invokable, Qt::QueuedConnection);
} else {
timerId = Qt::TimerId{startTimer(interval, 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 > Qt::TimerId::Invalid)
killTimer(std::exchange(timerId, Qt::TimerId::Invalid));
Q_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...
delete this;
}
QT_END_NAMESPACE
#endif // QSINGLESHOTTIMER_P_H