QChronoTimer: remove static singleShot() functions
They match what QTimer already provides these days, and we want to minimize porting for users come Qt 7, so we don't want users to first write QChronoTimer::singleShot() (because it exists) and then back to QTimer::singleShot(); we want them to continue to use QTimer. The only reason QChronoTimer is a separate class from QTimer is that the latter has an int interval property and we can't just port it to milli- or nanoseconds chrono types if we want users to actually access the extra range or precision afforded by the chrono types. But that's not an issue for the singleShot() static methods, as they never return an object that could be asked for its timeout. (No ChangeLog needed, as QChronoTimer is new in 6.8) Found in API-review. Fixes: QTBUG-128426 Change-Id: Ief8b7c8d25380c0e9e9c5c36c90ce34c147557ae Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> (cherry picked from commit 6e5eb082c934cb94c45f3e13b3f7c2deb2e7b2e6) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
2fb422828e
commit
f8b3c1f0a7
@ -38,9 +38,8 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
You can set a timer to time out only once by calling setSingleShot(true).
|
||||
|
||||
QChronoTimer also has singleShot() static methods:
|
||||
|
||||
\snippet timers/timers.cpp qchronotimer-singleshot
|
||||
\note QChronoTimer has no singleShot() static methods, as the ones on
|
||||
QTimer already work with chrono types and nanoseconds resolution.
|
||||
|
||||
In multithreaded applications, you can use QChronoTimer in any thread
|
||||
that has an event loop. To start an event loop from a non-GUI
|
||||
@ -360,96 +359,6 @@ QBindable<Qt::TimerType> QChronoTimer::bindableTimerType()
|
||||
return {&d_func()->type};
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
\reentrant
|
||||
|
||||
This static function calls the slot \a member, on object \a receiver, after
|
||||
time interval \a interval. \a timerType affects the precision of the timer
|
||||
|
||||
\a member has to be a member function of \a receiver; you need to use the
|
||||
\c SLOT() macro to get this parameter.
|
||||
|
||||
This function is provided as a convenience to save the need to use a
|
||||
\l{QObject::timerEvent()}{timerEvent} or create a local QChronoTimer
|
||||
object.
|
||||
|
||||
\sa start(), Qt::TimerType
|
||||
*/
|
||||
void QChronoTimer::singleShot(std::chrono::nanoseconds interval, Qt::TimerType timerType,
|
||||
const QObject *receiver, const char *member)
|
||||
{
|
||||
if (Q_UNLIKELY(interval < 0ns)) {
|
||||
qWarning("QChronoTimer::singleShot: Timers cannot have negative timeouts");
|
||||
return;
|
||||
}
|
||||
if (receiver && member) {
|
||||
if (interval == 0ns) {
|
||||
// special code shortpath for 0-timers
|
||||
const char* bracketPosition = strchr(member, '(');
|
||||
if (!bracketPosition || !(member[0] >= '0' && member[0] <= '2')) {
|
||||
qWarning("QChronoTimer::singleShot: Invalid slot specification");
|
||||
return;
|
||||
}
|
||||
const auto methodName = QByteArrayView(member + 1, // extract method name
|
||||
bracketPosition - 1 - member).trimmed();
|
||||
QMetaObject::invokeMethod(const_cast<QObject *>(receiver),
|
||||
methodName.toByteArray().constData(),
|
||||
Qt::QueuedConnection);
|
||||
return;
|
||||
}
|
||||
(void) new QSingleShotTimer(interval, timerType, receiver, member);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
\list
|
||||
\li \a interval the time interval
|
||||
\li \a timerType the type of the timer; this affects the precision of
|
||||
the timer
|
||||
\li \a receiver the receiver or context object; if this is \c nullptr,
|
||||
this method will figure out a context object to use, see code
|
||||
comments below
|
||||
\li \a slotObj a callable, for example a lambda
|
||||
\endlist
|
||||
*/
|
||||
void QChronoTimer::singleShotImpl(std::chrono::nanoseconds interval, Qt::TimerType timerType,
|
||||
const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj)
|
||||
{
|
||||
if (interval == 0ns) {
|
||||
bool deleteReceiver = false;
|
||||
// Optimize: set a receiver context when none is given, such that we can use
|
||||
// QMetaObject::invokeMethod which is more efficient than going through a timer.
|
||||
// We need a QObject living in the current thread. But the QThread itself lives
|
||||
// in a different thread - with the exception of the main QThread which lives in
|
||||
// itself. And QThread::currentThread() is among the few QObjects we know that will
|
||||
// most certainly be there. Note that one can actually call singleShot before the
|
||||
// QApplication is created!
|
||||
if (!receiver && QThread::currentThread() == QCoreApplicationPrivate::mainThread()) {
|
||||
// reuse main thread as context object
|
||||
receiver = QThread::currentThread();
|
||||
} else if (!receiver) {
|
||||
// Create a receiver context object on-demand. According to the benchmarks,
|
||||
// this is still more efficient than going through a timer.
|
||||
receiver = new QObject;
|
||||
deleteReceiver = true;
|
||||
}
|
||||
|
||||
auto h = QtPrivate::invokeMethodHelper({});
|
||||
QMetaObject::invokeMethodImpl(const_cast<QObject *>(receiver), slotObj,
|
||||
Qt::QueuedConnection, h.parameterCount(), h.parameters.data(), h.typeNames.data(),
|
||||
h.metaTypes.data());
|
||||
|
||||
if (deleteReceiver)
|
||||
const_cast<QObject *>(receiver)->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
new QSingleShotTimer(interval, timerType, receiver, slotObj);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#include "moc_qchronotimer.cpp"
|
||||
|
@ -55,49 +55,6 @@ public:
|
||||
bool isSingleShot() const;
|
||||
QBindable<bool> bindableSingleShot();
|
||||
|
||||
// singleShot with context
|
||||
#ifdef Q_QDOC
|
||||
template <typename Functor>
|
||||
static inline void singleShot(std::chrono::nanoseconds interval,
|
||||
const QObject *receiver, Functor &&slot);
|
||||
template <typename Functor>
|
||||
static inline void singleShot(std::chrono::nanoseconds interval interval,
|
||||
Qt::TimerType timerType,
|
||||
const QObject *receiver, Functor &&slot);
|
||||
#else
|
||||
template <typename Functor>
|
||||
static void singleShot(std::chrono::nanoseconds interval,
|
||||
const FunctorContext<Functor> *receiver, Functor &&slot)
|
||||
{
|
||||
singleShot(interval, QTimer::defaultTypeFor(interval), receiver, std::forward<Functor>(slot));
|
||||
}
|
||||
template <typename Functor>
|
||||
static void singleShot(std::chrono::nanoseconds interval, Qt::TimerType timerType,
|
||||
const FunctorContext<Functor> *receiver, Functor &&slot)
|
||||
{
|
||||
using Prototype = void(*)();
|
||||
auto *slotObj = QtPrivate::makeCallableObject<Prototype>(std::forward<Functor>(slot));
|
||||
singleShotImpl(interval, timerType, receiver, slotObj);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename Functor>
|
||||
static void singleShot(std::chrono::nanoseconds interval, Qt::TimerType timerType,
|
||||
Functor &&slot)
|
||||
{ singleShot(interval, timerType, nullptr, std::forward<Functor>(slot)); }
|
||||
|
||||
template <typename Functor>
|
||||
static void singleShot(std::chrono::nanoseconds interval, Functor &&slot)
|
||||
{
|
||||
singleShot(interval, QTimer::defaultTypeFor(interval), nullptr, std::forward<Functor>(slot));
|
||||
}
|
||||
|
||||
static void singleShot(std::chrono::nanoseconds interval, Qt::TimerType timerType,
|
||||
const QObject *receiver, const char *member);
|
||||
static void singleShot(std::chrono::nanoseconds interval, const QObject *receiver,
|
||||
const char *member)
|
||||
{ singleShot(interval, QTimer::defaultTypeFor(interval), receiver, member); }
|
||||
|
||||
#ifdef Q_QDOC
|
||||
template <typename Functor>
|
||||
QMetaObject::Connection callOnTimeout(const QObject *context, Functor &&slot,
|
||||
@ -132,9 +89,6 @@ private:
|
||||
// These two functions are inherited from QObject
|
||||
int startTimer(std::chrono::nanoseconds) = delete;
|
||||
void killTimer(int) = delete;
|
||||
|
||||
static void singleShotImpl(std::chrono::nanoseconds interval, Qt::TimerType timerType,
|
||||
const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj);
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -472,8 +472,8 @@ public:
|
||||
inTimerEvent = true;
|
||||
|
||||
QEventLoop eventLoop;
|
||||
QChronoTimer::singleShot(std::max<std::chrono::nanoseconds>(100ms, interval * 2),
|
||||
&eventLoop, &QEventLoop::quit);
|
||||
QTimer::singleShot(std::max<std::chrono::nanoseconds>(100ms, interval * 2),
|
||||
&eventLoop, &QEventLoop::quit);
|
||||
eventLoop.exec();
|
||||
|
||||
inTimerEvent = false;
|
||||
@ -501,8 +501,8 @@ void tst_QChronoTimer::timerInfiniteRecursion()
|
||||
(void) object.startTimer(interval);
|
||||
|
||||
QEventLoop eventLoop;
|
||||
QChronoTimer::singleShot(std::max<std::chrono::nanoseconds>(100ms, interval * 2), &eventLoop,
|
||||
&QEventLoop::quit);
|
||||
QTimer::singleShot(std::max<std::chrono::nanoseconds>(100ms, interval * 2),
|
||||
&eventLoop, &QEventLoop::quit);
|
||||
eventLoop.exec();
|
||||
|
||||
QVERIFY(!object.timerEventRecursed);
|
||||
@ -527,7 +527,7 @@ public:
|
||||
Q_EMIT done();
|
||||
} if (recurse) {
|
||||
QEventLoop eventLoop;
|
||||
QChronoTimer::singleShot(100ms, &eventLoop, &QEventLoop::quit);
|
||||
QTimer::singleShot(100ms, &eventLoop, &QEventLoop::quit);
|
||||
eventLoop.exec();
|
||||
}
|
||||
}
|
||||
@ -804,7 +804,7 @@ public slots:
|
||||
void tst_QChronoTimer::recurseOnTimeoutAndStopTimer()
|
||||
{
|
||||
QEventLoop eventLoop;
|
||||
QChronoTimer::singleShot(1s, &eventLoop, &QEventLoop::quit);
|
||||
QTimer::singleShot(1s, &eventLoop, &QEventLoop::quit);
|
||||
|
||||
RecursOnTimeoutAndStopTimerTimer t;
|
||||
t.one = new QChronoTimer(&t);
|
||||
@ -1173,16 +1173,16 @@ public:
|
||||
switch (callType)
|
||||
{
|
||||
case String:
|
||||
QChronoTimer::singleShot(0ns, this, SLOT(stringSlot()));
|
||||
QTimer::singleShot(0ns, this, SLOT(stringSlot()));
|
||||
break;
|
||||
case PMF:
|
||||
QChronoTimer::singleShot(0ns, this, &OrderHelper::pmfSlot);
|
||||
QTimer::singleShot(0ns, this, &OrderHelper::pmfSlot);
|
||||
break;
|
||||
case Functor:
|
||||
QChronoTimer::singleShot(0ns, this, [this]() { functorSlot(); });
|
||||
QTimer::singleShot(0ns, this, [this]() { functorSlot(); });
|
||||
break;
|
||||
case FunctorNoCtx:
|
||||
QChronoTimer::singleShot(0ns, [this]() { functorNoCtxSlot(); });
|
||||
QTimer::singleShot(0ns, [this]() { functorNoCtxSlot(); });
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user