diff options
author | Marc Mutz <marc.mutz@kdab.com> | 2019-06-26 23:35:12 +0200 |
---|---|---|
committer | Marc Mutz <marc.mutz@kdab.com> | 2021-07-29 15:00:35 +0200 |
commit | c61d9873e5e30723bc5558b509b3320f2abf1da7 (patch) | |
tree | 1d8faae9f9b9b7452e14231a37acf94a6d44834c /src/corelib/kernel/qobject_p.h | |
parent | 59df5dacd55b607ec1b59864cfcc8ab86d38d537 (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.h | 35 |
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 |