mirror of https://github.com/qt/qtgrpc.git
QGrpcCallOptions: transform into implicitly shared value class
As this class is copyable and really looks like a implicitly shared value class transform it into such. Also provide the missing testcase to this class. Task-number: QTBUG-123625 Pick-to: 6.8 Change-Id: Ibdd24155a04b0ba8a622998cbc482428965e2288 Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
This commit is contained in:
parent
88342e4f19
commit
d70fd4b305
|
|
@ -1,10 +1,10 @@
|
|||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||
|
||||
#include <QtGrpc/private/qtgrpcglobal_p.h>
|
||||
#include <QtGrpc/qgrpccalloptions.h>
|
||||
|
||||
#include <QtCore/qdebug.h>
|
||||
#include <QtCore/qvariant.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
|
@ -20,22 +20,19 @@ using namespace Qt::StringLiterals;
|
|||
that are used by gRPC channels to communicate with the services.
|
||||
*/
|
||||
|
||||
class QGrpcCallOptionsPrivate
|
||||
class QGrpcCallOptionsPrivate : public QSharedData
|
||||
{
|
||||
public:
|
||||
std::optional<QGrpcDuration> deadline;
|
||||
QGrpcMetadata metadata;
|
||||
};
|
||||
|
||||
static void dPtrDeleter(QGrpcCallOptionsPrivate *ptr)
|
||||
{
|
||||
delete ptr;
|
||||
}
|
||||
QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QGrpcCallOptionsPrivate)
|
||||
|
||||
/*!
|
||||
Constructs an empty QGrpcCallOptions object.
|
||||
*/
|
||||
QGrpcCallOptions::QGrpcCallOptions() : dPtr(new QGrpcCallOptionsPrivate(), dPtrDeleter)
|
||||
QGrpcCallOptions::QGrpcCallOptions() : d_ptr(new QGrpcCallOptionsPrivate())
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -47,21 +44,13 @@ QGrpcCallOptions::~QGrpcCallOptions() = default;
|
|||
/*!
|
||||
Construct a copy of QGrpcCallOptions with \a other object.
|
||||
*/
|
||||
QGrpcCallOptions::QGrpcCallOptions(const QGrpcCallOptions &other)
|
||||
: dPtr(new QGrpcCallOptionsPrivate(*other.dPtr), dPtrDeleter)
|
||||
{
|
||||
}
|
||||
QGrpcCallOptions::QGrpcCallOptions(const QGrpcCallOptions &other) = default;
|
||||
|
||||
/*!
|
||||
Assigns \a other to this QGrpcCallOptions and returns a reference to this
|
||||
QGrpcCallOptions.
|
||||
*/
|
||||
QGrpcCallOptions &QGrpcCallOptions::operator=(const QGrpcCallOptions &other)
|
||||
{
|
||||
if (this != &other)
|
||||
*dPtr = *other.dPtr;
|
||||
return *this;
|
||||
}
|
||||
QGrpcCallOptions &QGrpcCallOptions::operator=(const QGrpcCallOptions &other) = default;
|
||||
|
||||
/*!
|
||||
\fn QGrpcCallOptions::QGrpcCallOptions(QGrpcCallOptions &&other) noexcept
|
||||
|
|
@ -82,6 +71,15 @@ QGrpcCallOptions &QGrpcCallOptions::operator=(const QGrpcCallOptions &other)
|
|||
value.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\since 6.8
|
||||
Constructs a new QVariant object from this QGrpcCallOptions.
|
||||
*/
|
||||
QGrpcCallOptions::operator QVariant() const
|
||||
{
|
||||
return QVariant::fromValue(*this);
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 6.8
|
||||
\fn void QGrpcCallOptions::swap(QGrpcCallOptions &other) noexcept
|
||||
|
|
@ -93,7 +91,11 @@ QGrpcCallOptions &QGrpcCallOptions::operator=(const QGrpcCallOptions &other)
|
|||
*/
|
||||
QGrpcCallOptions &QGrpcCallOptions::setDeadline(QGrpcDuration deadline)
|
||||
{
|
||||
dPtr->deadline = deadline;
|
||||
if (d_ptr->deadline == deadline)
|
||||
return *this;
|
||||
d_ptr.detach();
|
||||
Q_D(QGrpcCallOptions);
|
||||
d->deadline = deadline;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -105,7 +107,11 @@ QGrpcCallOptions &QGrpcCallOptions::setDeadline(QGrpcDuration deadline)
|
|||
*/
|
||||
QGrpcCallOptions &QGrpcCallOptions::setMetadata(const QGrpcMetadata &metadata)
|
||||
{
|
||||
dPtr->metadata = metadata;
|
||||
if (d_ptr->metadata == metadata)
|
||||
return *this;
|
||||
d_ptr.detach();
|
||||
Q_D(QGrpcCallOptions);
|
||||
d->metadata = metadata;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -114,9 +120,13 @@ QGrpcCallOptions &QGrpcCallOptions::setMetadata(const QGrpcMetadata &metadata)
|
|||
|
||||
\sa setMetadata()
|
||||
*/
|
||||
QGrpcCallOptions &QGrpcCallOptions::setMetadata(QGrpcMetadata &&metadata) noexcept
|
||||
QGrpcCallOptions &QGrpcCallOptions::setMetadata(QGrpcMetadata &&metadata)
|
||||
{
|
||||
dPtr->metadata = std::move(metadata);
|
||||
if (d_ptr->metadata == metadata)
|
||||
return *this;
|
||||
d_ptr.detach();
|
||||
Q_D(QGrpcCallOptions);
|
||||
d->metadata = std::move(metadata);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -131,7 +141,8 @@ QGrpcCallOptions &QGrpcCallOptions::setMetadata(QGrpcMetadata &&metadata) noexce
|
|||
*/
|
||||
std::optional<QGrpcDuration> QGrpcCallOptions::deadline() const noexcept
|
||||
{
|
||||
return dPtr->deadline;
|
||||
Q_D(const QGrpcCallOptions);
|
||||
return d->deadline;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -144,12 +155,16 @@ std::optional<QGrpcDuration> QGrpcCallOptions::deadline() const noexcept
|
|||
*/
|
||||
const QGrpcMetadata &QGrpcCallOptions::metadata() const & noexcept
|
||||
{
|
||||
return dPtr->metadata;
|
||||
Q_D(const QGrpcCallOptions);
|
||||
return d->metadata;
|
||||
}
|
||||
|
||||
QGrpcMetadata QGrpcCallOptions::metadata() && noexcept
|
||||
QGrpcMetadata QGrpcCallOptions::metadata() &&
|
||||
{
|
||||
return std::move(dPtr->metadata);
|
||||
Q_D(QGrpcCallOptions);
|
||||
if (d->ref.loadRelaxed() != 1) // return copy if shared
|
||||
return { d->metadata };
|
||||
return std::move(d->metadata);
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
|
|
@ -160,9 +175,8 @@ QGrpcMetadata QGrpcCallOptions::metadata() && noexcept
|
|||
*/
|
||||
QDebug operator<<(QDebug debug, const QGrpcCallOptions &callOpts)
|
||||
{
|
||||
QDebugStateSaver save(debug);
|
||||
debug.nospace();
|
||||
debug.noquote();
|
||||
const QDebugStateSaver save(debug);
|
||||
debug.nospace().noquote();
|
||||
debug << "QGrpcCallOptions(deadline: " << callOpts.deadline()
|
||||
<< ", metadata: " << callOpts.metadata() << ')';
|
||||
return debug;
|
||||
|
|
|
|||
|
|
@ -7,15 +7,19 @@
|
|||
#include <QtGrpc/qgrpcdefs.h>
|
||||
#include <QtGrpc/qtgrpcglobal.h>
|
||||
|
||||
#include <QtCore/qshareddata.h>
|
||||
#include <QtCore/qstringfwd.h>
|
||||
#include <QtCore/qtclasshelpermacros.h>
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QDebug;
|
||||
class QVariant;
|
||||
|
||||
class QGrpcCallOptionsPrivate;
|
||||
QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QGrpcCallOptionsPrivate, Q_GRPC_EXPORT)
|
||||
|
||||
class QGrpcCallOptions final
|
||||
{
|
||||
|
|
@ -27,26 +31,32 @@ public:
|
|||
Q_GRPC_EXPORT QGrpcCallOptions &operator=(const QGrpcCallOptions &other);
|
||||
|
||||
QGrpcCallOptions(QGrpcCallOptions &&other) noexcept = default;
|
||||
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QGrpcCallOptions)
|
||||
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QGrpcCallOptions)
|
||||
|
||||
void swap(QGrpcCallOptions &other) noexcept { dPtr.swap(other.dPtr); }
|
||||
Q_GRPC_EXPORT Q_IMPLICIT operator QVariant() const;
|
||||
|
||||
void swap(QGrpcCallOptions &other) noexcept { d_ptr.swap(other.d_ptr); }
|
||||
|
||||
Q_GRPC_EXPORT QGrpcCallOptions &setDeadline(QGrpcDuration deadline);
|
||||
Q_GRPC_EXPORT QGrpcCallOptions &setMetadata(const QGrpcMetadata &metadata);
|
||||
Q_GRPC_EXPORT QGrpcCallOptions &setMetadata(QGrpcMetadata &&metadata) noexcept;
|
||||
Q_GRPC_EXPORT QGrpcCallOptions &setMetadata(QGrpcMetadata &&metadata);
|
||||
|
||||
[[nodiscard]] Q_GRPC_EXPORT std::optional<QGrpcDuration> deadline() const noexcept;
|
||||
[[nodiscard]] Q_GRPC_EXPORT const QGrpcMetadata &metadata() const & noexcept;
|
||||
[[nodiscard]] Q_GRPC_EXPORT QGrpcMetadata metadata() && noexcept;
|
||||
[[nodiscard]] Q_GRPC_EXPORT QGrpcMetadata metadata() &&;
|
||||
|
||||
private:
|
||||
std::unique_ptr<QGrpcCallOptionsPrivate, void (*)(QGrpcCallOptionsPrivate *)> dPtr;
|
||||
QExplicitlySharedDataPointer<QGrpcCallOptionsPrivate> d_ptr;
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
friend Q_GRPC_EXPORT QDebug operator<<(QDebug debug, const QGrpcCallOptions &callOpts);
|
||||
#endif
|
||||
|
||||
Q_DECLARE_PRIVATE(QGrpcCallOptions)
|
||||
};
|
||||
|
||||
Q_DECLARE_SHARED(QGrpcCallOptions)
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QGRPCALLOPTIONS_H
|
||||
|
|
|
|||
|
|
@ -10,4 +10,5 @@ if(TARGET WrapgRPC::WrapLibgRPC)
|
|||
add_subdirectory(qgrpchttp2channel)
|
||||
add_subdirectory(qgrpcserializationformat)
|
||||
add_subdirectory(qgrpcstatus)
|
||||
add_subdirectory(qgrpccalloptions)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
# Copyright (C) 2024 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(tst_qgrpccalloptions LANGUAGES CXX)
|
||||
find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
|
||||
endif()
|
||||
|
||||
qt_internal_add_test(tst_qgrpccalloptions
|
||||
SOURCES
|
||||
tst_qgrpccalloptions.cpp
|
||||
LIBRARIES
|
||||
Qt::Core
|
||||
Qt::Test
|
||||
Qt::Grpc
|
||||
)
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
// Copyright (C) 2024 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||
|
||||
#include <QtGrpc/qgrpccalloptions.h>
|
||||
|
||||
#include <QtTest/qtest.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
class QGrpcCallOptionsTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
void hasSpecialMemberFunctions() const;
|
||||
void hasImplicitQVariant() const;
|
||||
void hasMemberSwap() const;
|
||||
void propertyMetadata() const;
|
||||
void propertyDeadline() const;
|
||||
void streamsToDebug() const;
|
||||
};
|
||||
|
||||
void QGrpcCallOptionsTest::hasSpecialMemberFunctions() const
|
||||
{
|
||||
QGrpcCallOptions o1;
|
||||
QVERIFY(!o1.deadline());
|
||||
QVERIFY(o1.metadata().empty());
|
||||
|
||||
o1.setDeadline(100ms);
|
||||
|
||||
QGrpcCallOptions o2(o1);
|
||||
QCOMPARE_EQ(o1.deadline(), o2.deadline());
|
||||
|
||||
QGrpcCallOptions o3 = o1;
|
||||
QCOMPARE_EQ(o1.deadline(), o3.deadline());
|
||||
|
||||
QGrpcCallOptions o4(std::move(o1));
|
||||
QCOMPARE_EQ(o4.deadline(), o2.deadline());
|
||||
|
||||
o1 = std::move(o4);
|
||||
QCOMPARE_EQ(o1.deadline(), o2.deadline());
|
||||
}
|
||||
|
||||
void QGrpcCallOptionsTest::hasImplicitQVariant() const
|
||||
{
|
||||
QGrpcCallOptions o1;
|
||||
o1.setDeadline(250ms);
|
||||
o1.setMetadata({
|
||||
{ "keyA", "valA" },
|
||||
{ "keyB", "valB" },
|
||||
});
|
||||
|
||||
QVariant v = o1;
|
||||
QCOMPARE_EQ(v.metaType(), QMetaType::fromType<QGrpcCallOptions>());
|
||||
const auto o2 = v.value<QGrpcCallOptions>();
|
||||
QCOMPARE_EQ(o1.metadata(), o2.metadata());
|
||||
QCOMPARE_EQ(o1.deadline(), o2.deadline());
|
||||
}
|
||||
|
||||
void QGrpcCallOptionsTest::hasMemberSwap() const
|
||||
{
|
||||
constexpr QGrpcDuration Dur = 50ms;
|
||||
|
||||
QGrpcCallOptions o1;
|
||||
o1.setDeadline(Dur);
|
||||
QGrpcCallOptions o2;
|
||||
|
||||
QCOMPARE_EQ(o1.deadline(), Dur);
|
||||
QVERIFY(!o2.deadline());
|
||||
o2.swap(o1);
|
||||
QCOMPARE_EQ(o2.deadline(), Dur);
|
||||
QVERIFY(!o1.deadline());
|
||||
swap(o2, o1);
|
||||
QCOMPARE_EQ(o1.deadline(), Dur);
|
||||
QVERIFY(!o2.deadline());
|
||||
}
|
||||
|
||||
void QGrpcCallOptionsTest::propertyMetadata() const
|
||||
{
|
||||
QGrpcMetadata md = {
|
||||
{ "keyA", "valA" },
|
||||
{ "keyB", "valB" },
|
||||
};
|
||||
|
||||
QGrpcCallOptions o1;
|
||||
auto o1Detach = o1;
|
||||
o1.setMetadata(md);
|
||||
QCOMPARE_EQ(o1.metadata(), md);
|
||||
QCOMPARE_NE(o1.metadata(), o1Detach.metadata());
|
||||
|
||||
QGrpcCallOptions o2;
|
||||
auto o2Detach = o2;
|
||||
o2.setMetadata(std::move(md));
|
||||
QCOMPARE_EQ(o2.metadata(), o1.metadata());
|
||||
QCOMPARE_NE(o2.metadata(), o2Detach.metadata());
|
||||
|
||||
QCOMPARE_EQ(std::move(o1).metadata(), o2.metadata());
|
||||
}
|
||||
|
||||
void QGrpcCallOptionsTest::propertyDeadline() const
|
||||
{
|
||||
constexpr QGrpcDuration Dur = 50ms;
|
||||
|
||||
QGrpcCallOptions o1;
|
||||
auto o1Detach = o1;
|
||||
o1.setDeadline(Dur);
|
||||
QCOMPARE_EQ(o1.deadline(), Dur);
|
||||
QCOMPARE_NE(o1.deadline(), o1Detach.deadline());
|
||||
}
|
||||
|
||||
void QGrpcCallOptionsTest::streamsToDebug() const
|
||||
{
|
||||
QGrpcCallOptions o;
|
||||
QString storage;
|
||||
QDebug dbg(&storage);
|
||||
dbg.noquote().nospace();
|
||||
|
||||
dbg << o;
|
||||
QVERIFY(!storage.isEmpty());
|
||||
|
||||
std::unique_ptr<char[]> ustr(QTest::toString(o));
|
||||
QCOMPARE_EQ(storage, QString::fromUtf8(ustr.get()));
|
||||
}
|
||||
|
||||
QTEST_MAIN(QGrpcCallOptionsTest)
|
||||
|
||||
#include "tst_qgrpccalloptions.moc"
|
||||
Loading…
Reference in New Issue