Skip to content

Commit

Permalink
Use QSlotObject helper to drastically simplify QTimer
Browse files Browse the repository at this point in the history
Change-Id: Iaeef5dcb5282eef834df62c7db09d05851bd7c2b
Reviewed-by: Thiago Macieira <[email protected]>
  • Loading branch information
vohi committed May 2, 2023
1 parent 2cd2789 commit ee30801
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 170 deletions.
121 changes: 11 additions & 110 deletions src/corelib/kernel/qtimer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -441,125 +441,26 @@ void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *receiv
}
}

/*! \fn template<typename PointerToMemberFunction> void QTimer::singleShot(int msec, const QObject *receiver, PointerToMemberFunction method)
\since 5.4
\overload
\reentrant
This static function calls a member function of a QObject after a given time interval.
It is very convenient to use this function because you do not need
to bother with a \l{QObject::timerEvent()}{timerEvent} or
create a local QTimer object.
The \a receiver is the receiving object and the \a method is the member function. The
time interval is \a msec milliseconds.
If \a receiver is destroyed before the interval occurs, the method will not be called.
The function will be run in the thread of \a receiver. The receiver's thread must have
a running Qt event loop.
\sa start()
*/

/*! \fn template<typename PointerToMemberFunction> void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *receiver, PointerToMemberFunction method)
\since 5.4
\overload
\reentrant
This static function calls a member function of a QObject after a given time interval.
It is very convenient to use this function because you do not need
to bother with a \l{QObject::timerEvent()}{timerEvent} or
create a local QTimer object.
The \a receiver is the receiving object and the \a method is the member function. The
time interval is \a msec milliseconds. The \a timerType affects the
accuracy of the timer.
If \a receiver is destroyed before the interval occurs, the method will not be called.
The function will be run in the thread of \a receiver. The receiver's thread must have
a running Qt event loop.
\sa start()
*/

/*! \fn template<typename Functor> void QTimer::singleShot(int msec, Functor functor)
/*! \fn template<typename Functor> void QTimer::singleShot(int msec, const QObject *context, Functor &&functor)
\fn template<typename Functor> void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *context, Functor &&functor)
\fn template<typename Functor> void QTimer::singleShot(int msec, Functor &&functor)
\fn template<typename Functor> void QTimer::singleShot(int msec, Qt::TimerType timerType, Functor &&functor)
\since 5.4
\overload
\reentrant
This static function calls \a functor after a given time interval.
This static function calls \a functor after \a msec milliseconds.
It is very convenient to use this function because you do not need
to bother with a \l{QObject::timerEvent()}{timerEvent} or
create a local QTimer object.
The time interval is \a msec milliseconds.
\sa start()
*/

/*! \fn template<typename Functor> void QTimer::singleShot(int msec, Qt::TimerType timerType, Functor functor)
\since 5.4
\overload
\reentrant
This static function calls \a functor after a given time interval.
It is very convenient to use this function because you do not need
to bother with a \l{QObject::timerEvent()}{timerEvent} or
create a local QTimer object.
The time interval is \a msec milliseconds. The \a timerType affects the
accuracy of the timer.
\sa start()
*/

/*! \fn template<typename Functor> void QTimer::singleShot(int msec, const QObject *context, Functor functor)
\since 5.4
\overload
\reentrant
This static function calls \a functor after a given time interval.
It is very convenient to use this function because you do not need
to bother with a \l{QObject::timerEvent()}{timerEvent} or
create a local QTimer object.
The time interval is \a msec milliseconds.
If \a context is destroyed before the interval occurs, the method will not be called.
The function will be run in the thread of \a context. The context's thread must have
a running Qt event loop.
\sa start()
*/

/*! \fn template<typename Functor> void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *context, Functor functor)
\since 5.4
\overload
\reentrant
This static function calls \a functor after a given time interval.
It is very convenient to use this function because you do not need
to bother with a \l{QObject::timerEvent()}{timerEvent} or
create a local QTimer object.
The time interval is \a msec milliseconds. The \a timerType affects the
accuracy of the timer.
If \a context is specified, then the \a functor will be called only if the
\a context object has not been destroyed before the interval occurs. The functor
will then be run the thread of \a context. The context's thread must have a
running Qt event loop.
If \a context is destroyed before the interval occurs, the method will not be called.
The function will be run in the thread of \a context. The context's thread must have
a running Qt event loop.
If \a functor is a member
function of \a context, then the function will be called on the object.
\sa start()
*/
Expand Down
89 changes: 29 additions & 60 deletions src/corelib/kernel/qtimer.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,81 +49,50 @@ class Q_CORE_EXPORT QTimer : public QObject
static void singleShot(int msec, const QObject *receiver, const char *member);
static void singleShot(int msec, Qt::TimerType timerType, const QObject *receiver, const char *member);

// singleShot with context
template <typename Duration, typename Func1>
static inline void singleShot(Duration interval,
#ifdef Q_QDOC
template<typename PointerToMemberFunction>
static void singleShot(int msec, const QObject *receiver, PointerToMemberFunction method);
template<typename PointerToMemberFunction>
static void singleShot(int msec, Qt::TimerType timerType, const QObject *receiver, PointerToMemberFunction method);
template<typename Functor>
static void singleShot(int msec, Functor functor);
template<typename Functor>
static void singleShot(int msec, Qt::TimerType timerType, Functor functor);
template<typename Functor, int>
static void singleShot(int msec, const QObject *context, Functor functor);
template<typename Functor, int>
static void singleShot(int msec, Qt::TimerType timerType, const QObject *context, Functor functor);
template <typename Functor>
QMetaObject::Connection callOnTimeout(Functor slot, Qt::ConnectionType connectionType = Qt::AutoConnection);
template <typename Functor>
QMetaObject::Connection callOnTimeout(const QObject *context, Functor slot, Qt::ConnectionType connectionType = Qt::AutoConnection);
template <typename MemberFunction>
QMetaObject::Connection callOnTimeout(const QObject *receiver, MemberFunction *slot, Qt::ConnectionType connectionType = Qt::AutoConnection);
const QObject *receiver,
#else
// singleShot to a QObject slot
template <typename Duration, typename Func1>
static inline void singleShot(Duration interval, const typename QtPrivate::FunctionPointer<Func1>::Object *receiver, Func1 slot)
{
singleShot(interval, defaultTypeFor(interval), receiver, slot);
}
template <typename Duration, typename Func1>
static inline void singleShot(Duration interval, Qt::TimerType timerType, const typename QtPrivate::FunctionPointer<Func1>::Object *receiver,
Func1 slot)
{
typedef QtPrivate::FunctionPointer<Func1> SlotType;

//compilation error if the slot has arguments.
static_assert(int(SlotType::ArgumentCount) == 0,
"The slot must not have any arguments.");
const typename QtPrivate::ContextTypeForFunctor<Func1>::ContextType *receiver,
#endif

singleShotImpl(interval, timerType, receiver,
new QtPrivate::QSlotObject<Func1, typename SlotType::Arguments, void>(slot));
}
// singleShot to a functor or function pointer (without context)
template <typename Duration, typename Func1>
static inline typename std::enable_if<!QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction &&
!std::is_same<const char*, Func1>::value, void>::type
singleShot(Duration interval, Func1 slot)
Func1 &&slot)
{
singleShot(interval, defaultTypeFor(interval), nullptr, std::move(slot));
singleShot(interval, defaultTypeFor(interval), receiver, std::forward<Func1>(slot));
}
template <typename Duration, typename Func1>
static inline typename std::enable_if<!QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction &&
!std::is_same<const char*, Func1>::value, void>::type
singleShot(Duration interval, Qt::TimerType timerType, Func1 slot)
static inline void singleShot(Duration interval, Qt::TimerType timerType,
#ifdef Q_QDOC
const QObject *receiver,
#else
const typename QtPrivate::ContextTypeForFunctor<Func1>::ContextType *receiver,
#endif
Func1 &&slot)
{
singleShot(interval, timerType, nullptr, std::move(slot));
using Prototype = void(*)();
singleShotImpl(interval, timerType, receiver,
QtPrivate::makeSlotObject<Prototype>(std::forward<Func1>(slot)));
}
// singleShot to a functor or function pointer (with context)
// singleShot without context
template <typename Duration, typename Func1>
static inline typename std::enable_if<!QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction &&
!std::is_same<const char*, Func1>::value, void>::type
singleShot(Duration interval, const QObject *context, Func1 slot)
static inline void singleShot(Duration interval, Func1 &&slot)
{
singleShot(interval, defaultTypeFor(interval), context, std::move(slot));
singleShot(interval, defaultTypeFor(interval), nullptr, std::forward<Func1>(slot));
}
template <typename Duration, typename Func1>
static inline typename std::enable_if<!QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction &&
!std::is_same<const char*, Func1>::value, void>::type
singleShot(Duration interval, Qt::TimerType timerType, const QObject *context, Func1 slot)
static inline void singleShot(Duration interval, Qt::TimerType timerType, Func1 &&slot)
{
//compilation error if the slot has arguments.
typedef QtPrivate::FunctionPointer<Func1> SlotType;
static_assert(int(SlotType::ArgumentCount) <= 0, "The slot must not have any arguments.");

singleShotImpl(interval, timerType, context,
new QtPrivate::QFunctorSlotObject<Func1, QtPrivate::List<>, void>(std::move(slot)));
singleShot(interval, timerType, nullptr, std::forward<Func1>(slot));
}

#ifdef Q_QDOC
template <typename Functor>
QMetaObject::Connection callOnTimeout(Functor &&slot, Qt::ConnectionType connectionType = Qt::AutoConnection);
template <typename Functor>
QMetaObject::Connection callOnTimeout(const QObject *context, Functor &&slot, Qt::ConnectionType connectionType = Qt::AutoConnection);
#else
template <typename ... Args>
QMetaObject::Connection callOnTimeout(Args && ...args)
{
Expand Down

0 comments on commit ee30801

Please sign in to comment.