QHttp1Configuration: make fit for release

- inline move special member functions and swap()
- add qHash() overload (EqualityComparable types should be QtHashable)
- unexport this non-polymoprphic class, export only individual members
- don't use a heap-allocated Private just to hold a single number
  - use inline storage until we actually need to use external state
  - limit the max. connections to 255 to fit into an 8-bit value
- document min/max of the numberOfConnectionsPerHost() property
- use qsizetype instead of un-Qt-ish unsigned int

Task-number: QTBUG-108215
Task-number: QTBUG-25280
Change-Id: Ia9841f2dbabd13219ffd813aff3947aa0c8bdc0c
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
Marc Mutz 2022-12-05 07:29:44 +01:00
parent be05bb749e
commit dfe03926b6
2 changed files with 92 additions and 51 deletions

View File

@ -3,10 +3,16 @@
#include "qhttp1configuration.h" #include "qhttp1configuration.h"
#include "qdebug.h" #include <QtCore/private/qnumeric_p.h>
#include <QtCore/qhashfunctions.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
// QHttp1ConfigurationPrivate is unused until we need it:
static_assert(sizeof(QHttp1Configuration) == sizeof(void*),
"You have added too many members to QHttp1Configuration::ShortData. "
"Decrease their size or switch to using a d-pointer.");
/*! /*!
\class QHttp1Configuration \class QHttp1Configuration
\brief The QHttp1Configuration class controls HTTP/1 parameters and settings. \brief The QHttp1Configuration class controls HTTP/1 parameters and settings.
@ -26,42 +32,45 @@ QT_BEGIN_NAMESPACE
\sa QNetworkRequest::setHttp1Configuration(), QNetworkRequest::http1Configuration(), QNetworkAccessManager \sa QNetworkRequest::setHttp1Configuration(), QNetworkRequest::http1Configuration(), QNetworkAccessManager
*/ */
class QHttp1ConfigurationPrivate : public QSharedData
{
public:
unsigned numberOfConnectionsPerHost = 6; // QHttpNetworkConnectionPrivate::defaultHttpChannelCount
};
/*! /*!
Default constructs a QHttp1Configuration object. Default constructs a QHttp1Configuration object.
*/ */
QHttp1Configuration::QHttp1Configuration() QHttp1Configuration::QHttp1Configuration()
: d(new QHttp1ConfigurationPrivate) : data{6, {}} // QHttpNetworkConnectionPrivate::defaultHttpChannelCount
{ {
} }
/*! /*!
Copy-constructs this QHttp1Configuration. Copy-constructs this QHttp1Configuration.
*/ */
QHttp1Configuration::QHttp1Configuration(const QHttp1Configuration &) = default; QHttp1Configuration::QHttp1Configuration(const QHttp1Configuration &)
= default;
/*! /*!
Move-constructs this QHttp1Configuration from \a other \fn QHttp1Configuration::QHttp1Configuration(QHttp1Configuration &&other)
Move-constructs this QHttp1Configuration from \a other.
\note The moved-from object \a other is placed in a
partially-formed state, in which the only valid operations are
destruction and assignment of a new value.
*/ */
QHttp1Configuration::QHttp1Configuration(QHttp1Configuration &&other) noexcept
{
swap(other);
}
/*! /*!
Copy-assigns \a other to this QHttp1Configuration. Copy-assigns \a other to this QHttp1Configuration.
*/ */
QHttp1Configuration &QHttp1Configuration::operator=(const QHttp1Configuration &) = default; QHttp1Configuration &QHttp1Configuration::operator=(const QHttp1Configuration &)
= default;
/*! /*!
\fn QHttp1Configuration &QHttp1Configuration::operator=(QHttp1Configuration &&)
Move-assigns \a other to this QHttp1Configuration. Move-assigns \a other to this QHttp1Configuration.
\note The moved-from object \a other is placed in a
partially-formed state, in which the only valid operations are
destruction and assignment of a new value.
*/ */
QHttp1Configuration &QHttp1Configuration::operator=(QHttp1Configuration &&) noexcept = default;
/*! /*!
Destructor. Destructor.
@ -70,35 +79,42 @@ QHttp1Configuration::~QHttp1Configuration()
= default; = default;
/*! /*!
Sets number of connections (default 6) to a http(s)://host:port Sets the number of connections (minimum: 1; maximum: 255)
used per http(s) \e{host}:\e{port} combination to \a number.
If \a number is 0, does nothing. If \a number is > 255, 255 is used.
\sa numberOfConnectionsPerHost \sa numberOfConnectionsPerHost
*/ */
void QHttp1Configuration::setNumberOfConnectionsPerHost(unsigned number) void QHttp1Configuration::setNumberOfConnectionsPerHost(qsizetype number)
{ {
if (number == 0) { auto n = qt_saturate<std::uint8_t>(number);
if (n == 0)
return; return;
} data.numConnectionsPerHost = n;
d->numberOfConnectionsPerHost = number;
}
/*!
Returns the number of connections (default 6) to a http(s)://host:port
\sa setNumberOfConnectionsPerHost
*/
unsigned QHttp1Configuration::numberOfConnectionsPerHost() const
{
return d->numberOfConnectionsPerHost;
} }
/*! /*!
Swaps this configuration with the \a other configuration. Returns the number of connections used per http(s) \c{host}:\e{port}
combination. The default is six (6).
\sa setNumberOfConnectionsPerHost
*/ */
void QHttp1Configuration::swap(QHttp1Configuration &other) noexcept qsizetype QHttp1Configuration::numberOfConnectionsPerHost() const
{ {
d.swap(other.d); return data.numConnectionsPerHost;
} }
/*!
\fn void QHttp1Configuration::swap(QHttp1Configuration &other)
Swaps this HTTP/1 configuration with \a other. This operation is very fast
and never fails.
*/
/*! /*!
\fn bool QHttp1Configuration::operator==(const QHttp1Configuration &lhs, const QHttp1Configuration &rhs) noexcept \fn bool QHttp1Configuration::operator==(const QHttp1Configuration &lhs, const QHttp1Configuration &rhs) noexcept
\since 6.5
Returns \c true if \a lhs and \a rhs represent the same set of HTTP/1 Returns \c true if \a lhs and \a rhs represent the same set of HTTP/1
parameters. parameters.
@ -106,20 +122,33 @@ void QHttp1Configuration::swap(QHttp1Configuration &other) noexcept
/*! /*!
\fn bool QHttp1Configuration::operator!=(const QHttp1Configuration &lhs, const QHttp1Configuration &rhs) noexcept \fn bool QHttp1Configuration::operator!=(const QHttp1Configuration &lhs, const QHttp1Configuration &rhs) noexcept
\since 6.5
Returns \c true if \a lhs and \a rhs do not represent the same set of Returns \c true if \a lhs and \a rhs do not represent the same set of
HTTP/1 parameters. HTTP/1 parameters.
*/ */
/*!
\fn size_t QHttp1Configuration::qHash(const QHttp1Configuration &key, size_t seed)
\since 6.5
Returns the hash value for the \a key, using \a seed to seed the calculation.
*/
/*! /*!
\internal \internal
*/ */
bool QHttp1Configuration::isEqual(const QHttp1Configuration &other) const noexcept bool QHttp1Configuration::equals(const QHttp1Configuration &other) const noexcept
{ {
if (d == other.d) return data.numConnectionsPerHost == other.data.numConnectionsPerHost;
return true; }
return d->numberOfConnectionsPerHost == other.d->numberOfConnectionsPerHost; /*!
\internal
*/
size_t QHttp1Configuration::hash(size_t seed) const noexcept
{
return qHash(data.numConnectionsPerHost, seed);
} }
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -6,7 +6,8 @@
#include <QtNetwork/qtnetworkglobal.h> #include <QtNetwork/qtnetworkglobal.h>
#include <QtCore/qshareddata.h> #include <utility>
#include <cstdint>
#ifndef Q_CLANG_QDOC #ifndef Q_CLANG_QDOC
QT_REQUIRE_CONFIG(http); QT_REQUIRE_CONFIG(http);
@ -15,33 +16,44 @@ QT_REQUIRE_CONFIG(http);
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QHttp1ConfigurationPrivate; class QHttp1ConfigurationPrivate;
class Q_NETWORK_EXPORT QHttp1Configuration class QHttp1Configuration
{ {
public: public:
QHttp1Configuration(); Q_NETWORK_EXPORT QHttp1Configuration();
QHttp1Configuration(const QHttp1Configuration &other); Q_NETWORK_EXPORT QHttp1Configuration(const QHttp1Configuration &other);
QHttp1Configuration(QHttp1Configuration &&other) noexcept; QHttp1Configuration(QHttp1Configuration &&other) noexcept
: d{std::exchange(other.d, nullptr)} {}
QHttp1Configuration &operator=(const QHttp1Configuration &other); Q_NETWORK_EXPORT QHttp1Configuration &operator=(const QHttp1Configuration &other);
QHttp1Configuration &operator=(QHttp1Configuration &&other) noexcept; QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QHttp1Configuration)
~QHttp1Configuration(); Q_NETWORK_EXPORT ~QHttp1Configuration();
void setNumberOfConnectionsPerHost(unsigned amount); Q_NETWORK_EXPORT void setNumberOfConnectionsPerHost(qsizetype amount);
unsigned numberOfConnectionsPerHost() const; Q_NETWORK_EXPORT qsizetype numberOfConnectionsPerHost() const;
void swap(QHttp1Configuration &other) noexcept; void swap(QHttp1Configuration &other) noexcept
{ qt_ptr_swap(d, other.d); }
private: private:
QSharedDataPointer<QHttp1ConfigurationPrivate> d; struct ShortData {
std::uint8_t numConnectionsPerHost;
char reserved[sizeof(void*) - sizeof(numConnectionsPerHost)];
};
union {
QHttp1ConfigurationPrivate *d;
ShortData data;
};
bool isEqual(const QHttp1Configuration &other) const noexcept; Q_NETWORK_EXPORT bool equals(const QHttp1Configuration &other) const noexcept;
Q_NETWORK_EXPORT size_t hash(size_t seed) const noexcept;
friend bool operator==(const QHttp1Configuration &lhs, const QHttp1Configuration &rhs) noexcept friend bool operator==(const QHttp1Configuration &lhs, const QHttp1Configuration &rhs) noexcept
{ return lhs.isEqual(rhs); } { return lhs.equals(rhs); }
friend bool operator!=(const QHttp1Configuration &lhs, const QHttp1Configuration &rhs) noexcept friend bool operator!=(const QHttp1Configuration &lhs, const QHttp1Configuration &rhs) noexcept
{ return !lhs.isEqual(rhs); } { return !lhs.equals(rhs); }
friend size_t qHash(const QHttp1Configuration &key, size_t seed = 0) noexcept { return key.hash(seed); }
}; };
Q_DECLARE_SHARED(QHttp1Configuration) Q_DECLARE_SHARED(QHttp1Configuration)