Cleanup QDBusPendingReply

Remove the limitation of max 8 arguments and clean up the
template code.

This required a bit of special work to ensure
QDBusPendingReply<void> works the same way
as QDBusPendingReply<>.

Change-Id: I8e822b2f97f0712746b917056ea8f3d5c219c7f6
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Lars Knoll 2020-09-08 12:42:52 +02:00
parent 720e2e0c92
commit abd1b7f306
2 changed files with 93 additions and 96 deletions

View File

@ -95,7 +95,7 @@
*/
/*!
\fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::QDBusPendingReply()
\fn template<typename... Types> QDBusPendingReply<Types...>::QDBusPendingReply()
Creates an empty QDBusPendingReply object. Without assigning a
QDBusPendingCall object to this reply, QDBusPendingReply cannot do
@ -103,7 +103,7 @@
*/
/*!
\fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::QDBusPendingReply(const QDBusPendingReply &other)
\fn template<typename... Types> QDBusPendingReply<Types...>::QDBusPendingReply(const QDBusPendingReply &other)
Creates a copy of the \a other QDBusPendingReply object. Just like
QDBusPendingCall and QDBusPendingCallWatcher, this QDBusPendingReply
@ -112,7 +112,7 @@
*/
/*!
\fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::QDBusPendingReply(const QDBusPendingCall &call)
\fn template<typename... Types> QDBusPendingReply<Types...>::QDBusPendingReply(const QDBusPendingCall &call)
Creates a QDBusPendingReply object that will take its contents from
the \a call pending asynchronous call. This QDBusPendingReply object
@ -120,7 +120,7 @@
*/
/*!
\fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::QDBusPendingReply(const QDBusMessage &message)
\fn template<typename... Types> QDBusPendingReply<Types...>::QDBusPendingReply(const QDBusMessage &message)
Creates a QDBusPendingReply object that will take its contents from
the message \a message. In this case, this object will be already
@ -130,7 +130,7 @@
*/
/*!
\fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> QDBusPendingReply &QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::operator=(const QDBusPendingReply &other)
\fn template<typename... Types> QDBusPendingReply &QDBusPendingReply<Types...>::operator=(const QDBusPendingReply &other)
Makes a copy of \a other and drops the reference to the current
pending call. If the current reference is to an unfinished pending
@ -140,7 +140,7 @@
*/
/*!
\fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> QDBusPendingReply &QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::operator=(const QDBusPendingCall &call)
\fn template<typename... Types> QDBusPendingReply &QDBusPendingReply<Types...>::operator=(const QDBusPendingCall &call)
Makes this object take its contents from the \a call pending call
and drops the reference to the current pending call. If the
@ -150,7 +150,7 @@
*/
/*!
\fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> QDBusPendingReply &QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::operator=(const QDBusMessage &message)
\fn template<typename... Types> QDBusPendingReply &QDBusPendingReply<Types...>::operator=(const QDBusMessage &message)
Makes this object take its contents from the \a message message
and drops the reference to the current pending call. If the
@ -172,7 +172,7 @@
*/
/*!
\fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> int QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::count() const
\fn template<typename... Types> int QDBusPendingReply<Types...>::count() const
Return the number of arguments the reply is supposed to have. This
number matches the number of non-void template parameters in this
@ -184,7 +184,7 @@
*/
/*!
\fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> QVariant QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::argumentAt(int index) const
\fn template<typename... Types> QVariant QDBusPendingReply<Types...>::argumentAt(int index) const
Returns the argument at position \a index in the reply's
contents. If the reply doesn't have that many elements, this
@ -199,7 +199,7 @@
*/
/*!
\fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> T1 QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::value() const
\fn template<typename... Types> T1 QDBusPendingReply<Types...>::value() const
Returns the first argument in this reply, cast to type \c T1 (the
first template parameter of this class). This is equivalent to
@ -217,7 +217,7 @@
*/
/*!
\fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::operator T1() const
\fn template<typename... Types> QDBusPendingReply<Types...>::operator T1() const
Returns the first argument in this reply, cast to type \c T1 (the
first template parameter of this class). This is equivalent to
@ -235,7 +235,7 @@
*/
/*!
\fn template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> void QDBusPendingReply<T1, T2, T3, T4, T5, T6, T7, T8>::waitForFinished()
\fn template<typename... Types> void QDBusPendingReply<Types...>::waitForFinished()
Suspends the execution of the calling thread until the reply is
received and processed. After this function returns, isFinished()
@ -245,27 +245,27 @@
\sa QDBusPendingCallWatcher::waitForFinished()
*/
QDBusPendingReplyData::QDBusPendingReplyData()
QDBusPendingReplyBase::QDBusPendingReplyBase()
: QDBusPendingCall(nullptr) // initialize base class empty
{
}
QDBusPendingReplyData::~QDBusPendingReplyData()
QDBusPendingReplyBase::~QDBusPendingReplyBase()
{
}
void QDBusPendingReplyData::assign(const QDBusPendingCall &other)
void QDBusPendingReplyBase::assign(const QDBusPendingCall &other)
{
QDBusPendingCall::operator=(other);
}
void QDBusPendingReplyData::assign(const QDBusMessage &message)
void QDBusPendingReplyBase::assign(const QDBusMessage &message)
{
d = new QDBusPendingCallPrivate(QDBusMessage(), nullptr); // drops the reference to the old one
d->replyMessage = message;
}
QVariant QDBusPendingReplyData::argumentAt(int index) const
QVariant QDBusPendingReplyBase::argumentAt(int index) const
{
if (!d)
return QVariant();
@ -275,7 +275,7 @@ QVariant QDBusPendingReplyData::argumentAt(int index) const
return d->replyMessage.arguments().value(index);
}
void QDBusPendingReplyData::setMetaTypes(int count, const int *types)
void QDBusPendingReplyBase::setMetaTypes(int count, const int *types)
{
Q_ASSERT(d);
const auto locker = qt_scoped_lock(d->mutex);

View File

@ -49,11 +49,11 @@
QT_BEGIN_NAMESPACE
class Q_DBUS_EXPORT QDBusPendingReplyData: public QDBusPendingCall
class Q_DBUS_EXPORT QDBusPendingReplyBase : public QDBusPendingCall
{
protected:
QDBusPendingReplyData();
~QDBusPendingReplyData();
QDBusPendingReplyBase();
~QDBusPendingReplyBase();
void assign(const QDBusPendingCall &call);
void assign(const QDBusMessage &message);
@ -62,79 +62,45 @@ protected:
};
namespace QDBusPendingReplyTypes {
template<int Index,
typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8>
template<int Index, typename T, typename... Types>
struct Select
{
typedef Select<Index - 1, T2, T3, T4, T5, T6, T7, T8, void> Next;
typedef Select<Index - 1, Types...> Next;
typedef typename Next::Type Type;
};
template<typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8>
struct Select<0, T1, T2, T3, T4, T5, T6, T7, T8>
template<typename T, typename... Types>
struct Select<0, T, Types...>
{
typedef T1 Type;
typedef T Type;
};
template<typename T1> inline int metaTypeFor(T1 * = nullptr)
{ return qMetaTypeId<T1>(); }
template<typename T> inline QMetaType metaTypeFor()
{ return QMetaType::fromType<T>(); }
// specialize for QVariant, allowing it to be used in place of QDBusVariant
template<> inline int metaTypeFor<QVariant>(QVariant *)
{ return qMetaTypeId<QDBusVariant>(); }
template<> inline QMetaType metaTypeFor<QVariant>()
{ return QMetaType::fromType<QDBusVariant>(); }
}
template<typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8>
struct ForEach
{
typedef ForEach<T2, T3, T4, T5, T6, T7, T8, void> Next;
enum { Total = Next::Total + 1 };
static inline void fillMetaTypes(int *p)
{
*p = metaTypeFor<T1>(nullptr);
Next::fillMetaTypes(++p);
}
};
template<>
struct ForEach<void, void, void, void, void, void, void, void>
{
enum { Total = 0 };
static inline void fillMetaTypes(int *)
{ }
};
struct TypeIsVoid {};
template <typename T> struct NotVoid { typedef T Type; };
template <> struct NotVoid<void> { typedef TypeIsVoid Type; };
} // namespace QDBusPendingReplyTypes
template<typename T1 = void, typename T2 = void, typename T3 = void, typename T4 = void,
typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void>
class QDBusPendingReply:
#ifdef Q_CLANG_QDOC
public QDBusPendingCall
#else
public QDBusPendingReplyData
#endif
template<typename... Types>
class QDBusPendingReply : public QDBusPendingReplyBase
{
typedef QDBusPendingReplyTypes::ForEach<T1, T2, T3, T4, T5, T6, T7, T8> ForEach;
template<int Index> struct Select :
QDBusPendingReplyTypes::Select<Index, T1, T2, T3, T4, T5, T6, T7, T8>
{
};
template<int Index> using Select = QDBusPendingReplyTypes::Select<Index, Types...>;
public:
enum { Count = ForEach::Total };
enum { Count = std::is_same_v<typename Select<0>::Type, void> ? 0 : sizeof...(Types) };
inline QDBusPendingReply()
{ }
inline constexpr int count() const { return Count; }
inline QDBusPendingReply() = default;
inline QDBusPendingReply(const QDBusPendingReply &other)
: QDBusPendingReplyData(other)
: QDBusPendingReplyBase(other)
{ }
inline /*implicit*/ QDBusPendingReply(const QDBusPendingCall &call) // required by qdbusxml2cpp-generated code
{ *this = call; }
inline /*implicit*/ QDBusPendingReply(const QDBusMessage &message)
{ *this = message; }
inline QDBusPendingReply &operator=(const QDBusPendingReply &other)
{ assign(other); return *this; }
inline QDBusPendingReply &operator=(const QDBusPendingCall &call)
@ -142,23 +108,14 @@ public:
inline QDBusPendingReply &operator=(const QDBusMessage &message)
{ assign(message); return *this; }
inline int count() const { return Count; }
#if defined(Q_CLANG_QDOC)
QVariant argumentAt(int index) const;
#else
using QDBusPendingReplyData::argumentAt;
#endif
#ifndef Q_CLANG_QDOC
using QDBusPendingReplyBase::argumentAt;
template<int Index> inline
const typename Select<Index>::Type argumentAt() const
typename Select<Index>::Type argumentAt() const
{
static_assert(Index >= 0 && Index < Count, "Index out of bounds");
typedef typename Select<Index>::Type ResultType;
return qdbus_cast<ResultType>(argumentAt(Index));
}
#endif
#if defined(Q_CLANG_QDOC)
bool isFinished() const;
@ -168,43 +125,83 @@ public:
bool isError() const;
QDBusError error() const;
QDBusMessage reply() const;
#endif
inline T1 value() const;
inline operator T1() const;
#else
inline typename Select<0>::Type value() const
{
return argumentAt<0>();
}
inline operator typename QDBusPendingReplyTypes::NotVoid<T1>::Type() const
inline operator typename Select<0>::Type() const
{
return argumentAt<0>();
}
#endif
private:
inline void calculateMetaTypes()
{
if (!d) return;
int typeIds[Count > 0 ? Count : 1]; // use at least one since zero-sized arrays aren't valid
ForEach::fillMetaTypes(typeIds);
setMetaTypes(Count, typeIds);
if constexpr (Count == 0) {
setMetaTypes(0, nullptr);
} else {
std::array<int, Count> typeIds = { QDBusPendingReplyTypes::metaTypeFor<Types>().id()... };
setMetaTypes(Count, typeIds.data());
}
}
inline void assign(const QDBusPendingCall &call)
{
QDBusPendingReplyData::assign(call);
QDBusPendingReplyBase::assign(call);
calculateMetaTypes();
}
inline void assign(const QDBusMessage &message)
{
QDBusPendingReplyData::assign(message);
QDBusPendingReplyBase::assign(message);
calculateMetaTypes();
}
};
template<>
class QDBusPendingReply<> : public QDBusPendingReplyBase
{
public:
enum { Count = 0 };
inline int count() const { return Count; }
inline QDBusPendingReply() = default;
inline QDBusPendingReply(const QDBusPendingReply &other)
: QDBusPendingReplyBase(other)
{ }
inline /*implicit*/ QDBusPendingReply(const QDBusPendingCall &call) // required by qdbusxml2cpp-generated code
{ *this = call; }
inline /*implicit*/ QDBusPendingReply(const QDBusMessage &message)
{ *this = message; }
inline QDBusPendingReply &operator=(const QDBusPendingReply &other)
{ assign(other); return *this; }
inline QDBusPendingReply &operator=(const QDBusPendingCall &call)
{ assign(call); return *this; }
inline QDBusPendingReply &operator=(const QDBusMessage &message)
{ assign(message); return *this; }
private:
inline void assign(const QDBusPendingCall &call)
{
QDBusPendingReplyBase::assign(call);
if (d)
setMetaTypes(0, nullptr);
}
inline void assign(const QDBusMessage &message)
{
QDBusPendingReplyBase::assign(message);
if (d)
setMetaTypes(0, nullptr);
}
};
QT_END_NAMESPACE
#endif // QT_NO_DBUS