summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qobject_p.h
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@kdab.com>2019-06-26 23:35:12 +0200
committerMarc Mutz <marc.mutz@kdab.com>2021-07-29 15:00:35 +0200
commitc61d9873e5e30723bc5558b509b3320f2abf1da7 (patch)
tree1d8faae9f9b9b7452e14231a37acf94a6d44834c /src/corelib/kernel/qobject_p.h
parent59df5dacd55b607ec1b59864cfcc8ab86d38d537 (diff)
QPrivateSlotBase: add empty base class optimization
There are few slots whose lambdas are empty; most will at least capture [this]. But there are a few in Qt examples that do, e.g. []{ qApp->quit(); }. Logging is also an example. So go the extra mile and optimize for empty functors by inheriting from them as opposed to storing them in a member variable. Change-Id: I3904f10db5ebe904ba889d29c08569edd804df3b Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Lars Knoll <lars.knoll@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/kernel/qobject_p.h')
-rw-r--r--src/corelib/kernel/qobject_p.h35
1 files changed, 30 insertions, 5 deletions
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
index 539818ac1d..c119fdfe7e 100644
--- a/src/corelib/kernel/qobject_p.h
+++ b/src/corelib/kernel/qobject_p.h
@@ -467,10 +467,35 @@ inline void QObjectPrivate::disconnectNotify(const QMetaMethod &signal)
}
namespace QtPrivate {
-template<typename Func, typename Args, typename R> class QPrivateSlotObject : public QSlotObjectBase
+
+template <typename Func>
+struct FunctionStorageByValue
+{
+ Func f;
+ Func &func() noexcept { return f; }
+};
+
+template <typename Func>
+struct FunctionStorageEmptyBaseClassOptimization : Func
+{
+ Func &func() noexcept { return *this; }
+ using Func::Func;
+};
+
+template <typename Func>
+using FunctionStorage = typename std::conditional_t<
+ std::conjunction_v<
+ std::is_empty<Func>,
+ std::negation<std::is_final<Func>>
+ >,
+ FunctionStorageEmptyBaseClassOptimization<Func>,
+ FunctionStorageByValue<Func>
+ >;
+
+template<typename Func, typename Args, typename R>
+class QPrivateSlotObject : public QSlotObjectBase, private FunctionStorage<Func>
{
typedef QtPrivate::FunctionPointer<Func> FuncType;
- Func function;
static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret)
{
switch (which) {
@@ -478,17 +503,17 @@ template<typename Func, typename Args, typename R> class QPrivateSlotObject : pu
delete static_cast<QPrivateSlotObject*>(this_);
break;
case Call:
- FuncType::template call<Args, R>(static_cast<QPrivateSlotObject*>(this_)->function,
+ FuncType::template call<Args, R>(static_cast<QPrivateSlotObject*>(this_)->func(),
static_cast<typename FuncType::Object *>(QObjectPrivate::get(r)), a);
break;
case Compare:
- *ret = *reinterpret_cast<Func *>(a) == static_cast<QPrivateSlotObject*>(this_)->function;
+ *ret = *reinterpret_cast<Func *>(a) == static_cast<QPrivateSlotObject*>(this_)->func();
break;
case NumOperations: ;
}
}
public:
- explicit QPrivateSlotObject(Func f) : QSlotObjectBase(&impl), function(f) {}
+ explicit QPrivateSlotObject(Func f) : QSlotObjectBase(&impl), FunctionStorage<Func>{std::move(f)} {}
};
} //namespace QtPrivate