QCallableObject: use QtPrivate::CompactStorage

... optimizing the storage of empty function objects.

I thought we had applied this a long time ago, but it turns out that
QPrivateSlotObject (c61d9873e5e30723bc5558b509b3320f2abf1da7) is only
for QObjectPrivate::connect()...

This adds the same optimization for regular QObject::connect(). This
is BC, since we don't touch the base class (QSlotObjectBase), and the
QCallableObject subclasses are all-inline or explicitly Q_DECL_HIDDEN.

Amends c61d9873e5e30723bc5558b509b3320f2abf1da7.

Change-Id: I63fd1b6f882b58f9f98eae67c636c3615248ad79
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Marc Mutz 2023-05-04 15:51:55 +02:00 committed by Thiago Macieira
parent aaccd50224
commit 3c3de181ef

View File

@ -12,6 +12,8 @@
#pragma qt_sync_stop_processing #pragma qt_sync_stop_processing
#endif #endif
#include <QtCore/qfunctionaltools_impl.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QObject; class QObject;
class QObjectPrivate; class QObjectPrivate;
@ -440,14 +442,16 @@ namespace QtPrivate {
// Implementation of QSlotObjectBase for which the slot is a callable (function, PMF, functor, or lambda). // Implementation of QSlotObjectBase for which the slot is a callable (function, PMF, functor, or lambda).
// Args and R are the List of arguments and the return type of the signal to which the slot is connected. // Args and R are the List of arguments and the return type of the signal to which the slot is connected.
template<typename Func, typename Args, typename R> class QCallableObject : public QSlotObjectBase template <typename Func, typename Args, typename R>
class QCallableObject : public QSlotObjectBase,
private QtPrivate::CompactStorage<std::decay_t<Func>>
{ {
using FunctorValue = std::decay_t<Func>; using FunctorValue = std::decay_t<Func>;
using Storage = QtPrivate::CompactStorage<FunctorValue>;
using FuncType = std::conditional_t<std::is_member_function_pointer_v<FunctorValue>, using FuncType = std::conditional_t<std::is_member_function_pointer_v<FunctorValue>,
QtPrivate::FunctionPointer<FunctorValue>, QtPrivate::FunctionPointer<FunctorValue>,
QtPrivate::Functor<FunctorValue, Args::size> QtPrivate::Functor<FunctorValue, Args::size>
>; >;
FunctorValue function;
Q_DECL_HIDDEN static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret) Q_DECL_HIDDEN static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret)
{ {
const auto that = static_cast<QCallableObject*>(this_); const auto that = static_cast<QCallableObject*>(this_);
@ -457,13 +461,13 @@ namespace QtPrivate {
break; break;
case Call: case Call:
if constexpr (std::is_member_function_pointer_v<FunctorValue>) if constexpr (std::is_member_function_pointer_v<FunctorValue>)
FuncType::template call<Args, R>(that->function, static_cast<typename FuncType::Object *>(r), a); FuncType::template call<Args, R>(that->object(), static_cast<typename FuncType::Object *>(r), a);
else else
FuncType::template call<Args, R>(that->function, r, a); FuncType::template call<Args, R>(that->object(), r, a);
break; break;
case Compare: case Compare:
if constexpr (std::is_member_function_pointer_v<FunctorValue>) { if constexpr (std::is_member_function_pointer_v<FunctorValue>) {
*ret = *reinterpret_cast<FunctorValue *>(a) == that->function; *ret = *reinterpret_cast<FunctorValue *>(a) == that->object();
break; break;
} }
// not implemented otherwise // not implemented otherwise
@ -473,8 +477,8 @@ namespace QtPrivate {
} }
} }
public: public:
explicit QCallableObject(Func &&f) : QSlotObjectBase(&impl), function(std::move(f)) {} explicit QCallableObject(Func &&f) : QSlotObjectBase(&impl), Storage{std::move(f)} {}
explicit QCallableObject(const Func &f) : QSlotObjectBase(&impl), function(f) {} explicit QCallableObject(const Func &f) : QSlotObjectBase(&impl), Storage{f} {}
}; };
// Helper to detect the context object type based on the functor type: // Helper to detect the context object type based on the functor type: