diff options
author | Marc Mutz <marc.mutz@qt.io> | 2023-01-13 10:11:46 +0100 |
---|---|---|
committer | Marc Mutz <marc.mutz@qt.io> | 2023-01-26 17:44:19 +0100 |
commit | cde904b38ab6ef1ddcc9a0cbcae766cf42d58d81 (patch) | |
tree | dc365ecc97262192317a5935448640ee2d227c43 /src/corelib | |
parent | ce9d708d514011db1ab45630c95222d2a30c7550 (diff) |
Q<Typed>Permission: don't use external state
There's no point in using the full implicit sharing machinery when the
type's state consists of two enums, a bool or, indeed, if the type has
no state at all. QRect has more state and isn't implicitly shared.
To remain extensible in the future, all that is required is that the
type contains space for an eventual d-pointer and that all access to
members (except swapping, and, as a consequence, the move SFMs, but
including the copy SMFs, ctors and dtor) is confined to out-of-line
functions.
So define a ShortData (name stolen from QDateTime) nested struct in
each of the stateful Q<Typed>Permission classes, of the same size as a
pointer, holding the trivially-relocatable fields we currently have.
If, in the future, fields are added such that the reserved[] space in
any given class' ShortData no longer suffices to hold them, or said
fields are not of Q_RELOCATABLE_TYPE, then the full d-pointer pattern
(with an actually defined Private, and detach()ing) can be implemented
_for that one class_.
The new-style classes are externally indistinguishable from the
implicitly-shared old-style ones, just a lot more efficient.
Inline the move-ctor, now that we can. This doesn't break
encapsulation, even when we eventually activate the d-pointer.
As a drive-by, drop the noexcept on the dtors - dtors are implicitly
noexcept, anyway.
Pick-to: 6.5
Change-Id: Id90a39227277c6554ddd5895e8205485da1e39ca
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/kernel/qpermissions.cpp | 88 | ||||
-rw-r--r-- | src/corelib/kernel/qpermissions.h | 42 |
2 files changed, 76 insertions, 54 deletions
diff --git a/src/corelib/kernel/qpermissions.cpp b/src/corelib/kernel/qpermissions.cpp index fa2b32bfa7..f8215fbe50 100644 --- a/src/corelib/kernel/qpermissions.cpp +++ b/src/corelib/kernel/qpermissions.cpp @@ -277,14 +277,17 @@ const void *QPermission::data(QMetaType requestedType) const return m_data.data(); } - - -#define QT_DEFINE_PERMISSION_SPECIAL_FUNCTIONS(ClassName) \ - ClassName::ClassName() : d(new ClassName##Private) {} \ +#define QT_PERMISSION_IMPL_COMMON(ClassName) \ + /* Class##Private is unused until we need it: */ \ + static_assert(sizeof(ClassName) == sizeof(void*), \ + "You have added too many members to " #ClassName "::ShortData. " \ + "Decrease their size or switch to using a d-pointer."); \ ClassName::ClassName(const ClassName &other) noexcept = default; \ - ClassName::ClassName(ClassName &&other) noexcept = default; \ - ClassName::~ClassName() noexcept = default; \ - ClassName &ClassName::operator=(const ClassName &other) noexcept = default; + ClassName::~ClassName() = default; \ + ClassName &ClassName::operator=(const ClassName &other) noexcept = default; \ + ClassName::ClassName() \ + /* impl supplied by caller */ + /*! \class QCameraPermission @@ -305,8 +308,10 @@ const void *QPermission::data(QMetaType requestedType) const \include permissions.qdocinc permission-metadata */ -class QCameraPermissionPrivate : public QSharedData {}; -QT_DEFINE_PERMISSION_SPECIAL_FUNCTIONS(QCameraPermission) + +QT_PERMISSION_IMPL_COMMON(QCameraPermission) + : u{} // stateless, atm +{} /*! \class QMicrophonePermission @@ -327,8 +332,10 @@ QT_DEFINE_PERMISSION_SPECIAL_FUNCTIONS(QCameraPermission) \include permissions.qdocinc permission-metadata */ -class QMicrophonePermissionPrivate : public QSharedData {}; -QT_DEFINE_PERMISSION_SPECIAL_FUNCTIONS(QMicrophonePermission) + +QT_PERMISSION_IMPL_COMMON(QMicrophonePermission) + : u{} // stateless, atm +{} /*! \class QBluetoothPermission @@ -349,8 +356,10 @@ QT_DEFINE_PERMISSION_SPECIAL_FUNCTIONS(QMicrophonePermission) \include permissions.qdocinc permission-metadata */ -class QBluetoothPermissionPrivate : public QSharedData {}; -QT_DEFINE_PERMISSION_SPECIAL_FUNCTIONS(QBluetoothPermission) + +QT_PERMISSION_IMPL_COMMON(QBluetoothPermission) + : u{} // stateless, atm +{} /*! \class QLocationPermission @@ -385,17 +394,10 @@ QT_DEFINE_PERMISSION_SPECIAL_FUNCTIONS(QBluetoothPermission) \include permissions.qdocinc permission-metadata */ -class QLocationPermissionPrivate : public QSharedData -{ -public: - using Accuracy = QLocationPermission::Accuracy; - Accuracy accuracy = Accuracy::Approximate; - - using Availability = QLocationPermission::Availability; - Availability availability = Availability::WhenInUse; -}; -QT_DEFINE_PERMISSION_SPECIAL_FUNCTIONS(QLocationPermission) +QT_PERMISSION_IMPL_COMMON(QLocationPermission) + : u{ShortData{Accuracy::Approximate, Availability::WhenInUse, {}}} +{} /*! \enum QLocationPermission::Accuracy @@ -422,8 +424,7 @@ QT_DEFINE_PERMISSION_SPECIAL_FUNCTIONS(QLocationPermission) */ void QLocationPermission::setAccuracy(Accuracy accuracy) { - d.detach(); - d->accuracy = accuracy; + u.data.accuracy = accuracy; } /*! @@ -431,7 +432,7 @@ void QLocationPermission::setAccuracy(Accuracy accuracy) */ QLocationPermission::Accuracy QLocationPermission::accuracy() const { - return d->accuracy; + return u.data.accuracy; } /*! @@ -439,8 +440,7 @@ QLocationPermission::Accuracy QLocationPermission::accuracy() const */ void QLocationPermission::setAvailability(Availability availability) { - d.detach(); - d->availability = availability; + u.data.availability = availability; } /*! @@ -448,7 +448,7 @@ void QLocationPermission::setAvailability(Availability availability) */ QLocationPermission::Availability QLocationPermission::availability() const { - return d->availability; + return u.data.availability; } /*! @@ -474,13 +474,10 @@ QLocationPermission::Availability QLocationPermission::availability() const \include permissions.qdocinc permission-metadata */ -class QContactsPermissionPrivate : public QSharedData -{ -public: - bool isReadWrite = false; -}; -QT_DEFINE_PERMISSION_SPECIAL_FUNCTIONS(QContactsPermission) +QT_PERMISSION_IMPL_COMMON(QContactsPermission) + : u{ShortData{false, {}}} +{} /*! Sets whether the request is for read-write (\a enable == \c true) or @@ -488,8 +485,7 @@ QT_DEFINE_PERMISSION_SPECIAL_FUNCTIONS(QContactsPermission) */ void QContactsPermission::setReadWrite(bool enable) { - d.detach(); - d->isReadWrite = enable; + u.data.readWrite = enable; } /*! @@ -498,7 +494,7 @@ void QContactsPermission::setReadWrite(bool enable) */ bool QContactsPermission::isReadWrite() const { - return d->isReadWrite; + return u.data.readWrite; } /*! @@ -524,13 +520,10 @@ bool QContactsPermission::isReadWrite() const \include permissions.qdocinc permission-metadata */ -class QCalendarPermissionPrivate : public QSharedData -{ -public: - bool isReadWrite = false; -}; -QT_DEFINE_PERMISSION_SPECIAL_FUNCTIONS(QCalendarPermission) +QT_PERMISSION_IMPL_COMMON(QCalendarPermission) + : u{ShortData{false, {}}} +{} /*! Sets whether the request is for read-write (\a enable == \c true) or @@ -538,8 +531,7 @@ QT_DEFINE_PERMISSION_SPECIAL_FUNCTIONS(QCalendarPermission) */ void QCalendarPermission::setReadWrite(bool enable) { - d.detach(); - d->isReadWrite = enable; + u.data.readWrite = enable; } /*! @@ -548,7 +540,7 @@ void QCalendarPermission::setReadWrite(bool enable) */ bool QCalendarPermission::isReadWrite() const { - return d->isReadWrite; + return u.data.readWrite; } /*! @@ -572,6 +564,8 @@ QDebug operator<<(QDebug debug, const QPermission &permission) } #endif +#undef QT_PERMISSION_IMPL_COMMON + QT_END_NAMESPACE #include "moc_qpermissions.cpp" diff --git a/src/corelib/kernel/qpermissions.h b/src/corelib/kernel/qpermissions.h index 7f56e9625e..7eff832446 100644 --- a/src/corelib/kernel/qpermissions.h +++ b/src/corelib/kernel/qpermissions.h @@ -78,21 +78,28 @@ private: Q_GADGET_EXPORT(Q_CORE_EXPORT) \ using QtPermissionHelper = void; \ friend class QPermission; \ + union U { \ + U() : d(nullptr) {} \ + U(ShortData _data) : data(_data) {} \ + U(ClassName##Private *_d) : d(_d) {} \ + ShortData data; \ + ClassName##Private *d; \ + } u; \ public: \ Q_CORE_EXPORT ClassName(); \ Q_CORE_EXPORT ClassName(const ClassName &other) noexcept; \ - Q_CORE_EXPORT ClassName(ClassName &&other) noexcept; \ - Q_CORE_EXPORT ~ClassName() noexcept; \ + ClassName(ClassName &&other) noexcept \ + : u{other.u} { other.u.d = nullptr; } \ + Q_CORE_EXPORT ~ClassName(); \ Q_CORE_EXPORT ClassName &operator=(const ClassName &other) noexcept; \ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(ClassName) \ - void swap(ClassName &other) noexcept { d.swap(other.d); } \ + void swap(ClassName &other) noexcept { std::swap(u, other.u); } \ private: \ - QtPrivate::QExplicitlySharedDataPointerV2<ClassName##Private> d; + /*end*/ class QLocationPermissionPrivate; class QLocationPermission { - QT_PERMISSION(QLocationPermission) public: enum Accuracy : quint8 { Approximate, @@ -111,26 +118,46 @@ public: Q_CORE_EXPORT void setAvailability(Availability availability); Q_CORE_EXPORT Availability availability() const; + +private: + struct ShortData { + Accuracy accuracy; + Availability availability; + char reserved[sizeof(void*) - sizeof(accuracy) - sizeof(availability)]; + }; + QT_PERMISSION(QLocationPermission) }; Q_DECLARE_SHARED(QLocationPermission) class QCalendarPermissionPrivate; class QCalendarPermission { - QT_PERMISSION(QCalendarPermission) public: Q_CORE_EXPORT void setReadWrite(bool enable); Q_CORE_EXPORT bool isReadWrite() const; + +private: + struct ShortData { + bool readWrite; + char reserved[sizeof(void*) - sizeof(readWrite)]; + }; + QT_PERMISSION(QCalendarPermission) }; Q_DECLARE_SHARED(QCalendarPermission) class QContactsPermissionPrivate; class QContactsPermission { - QT_PERMISSION(QContactsPermission) public: Q_CORE_EXPORT void setReadWrite(bool enable); Q_CORE_EXPORT bool isReadWrite() const; + +private: + struct ShortData { + bool readWrite; + char reserved[sizeof(void*) - sizeof(readWrite)]; + }; + QT_PERMISSION(QContactsPermission) }; Q_DECLARE_SHARED(QContactsPermission) @@ -138,6 +165,7 @@ Q_DECLARE_SHARED(QContactsPermission) class ClassName##Private; \ class ClassName \ { \ + struct ShortData { char reserved[sizeof(void*)]; }; \ QT_PERMISSION(ClassName) \ }; \ Q_DECLARE_SHARED(ClassName) |