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
parent
59df5dacd5
commit
c61d9873e5
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue