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>
bb10
Marc Mutz 2019-06-26 23:35:12 +02:00
parent 59df5dacd5
commit c61d9873e5
2 changed files with 31 additions and 6 deletions

View File

@ -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

View File

@ -5221,7 +5221,7 @@ namespace ManyArgumentNamespace {
}
};
struct Funct6 {
struct Funct6 final {
void operator()(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e, const QString&f) {
MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c);
MANYARGUMENT_COMPARE(d); MANYARGUMENT_COMPARE(e); MANYARGUMENT_COMPARE(f);