summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@qt.io>2023-01-13 10:11:46 +0100
committerMarc Mutz <marc.mutz@qt.io>2023-01-26 17:44:19 +0100
commitcde904b38ab6ef1ddcc9a0cbcae766cf42d58d81 (patch)
treedc365ecc97262192317a5935448640ee2d227c43 /src/corelib
parentce9d708d514011db1ab45630c95222d2a30c7550 (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.cpp88
-rw-r--r--src/corelib/kernel/qpermissions.h42
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)