Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qshareddata.h
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#ifndef QSHAREDDATA_H
6#define QSHAREDDATA_H
7
8#include <QtCore/qatomic.h>
9#include <QtCore/qcompare.h>
10#include <QtCore/qhashfunctions.h>
11
13
14template <class T> class QSharedDataPointer;
15template <class T> class QExplicitlySharedDataPointer;
16
17namespace QtPrivate {
18template <template <typename> class P, typename T> struct QSharedDataPointerTraits;
19template <typename T> struct QSharedDataPointerTraits<QSharedDataPointer, T>
20{
21 static constexpr bool ImplicitlyDetaches = true;
22 using Type = T;
23 using pointer = T *;
24 // for const-qualified functions:
25 using constT = const T;
26};
27
29{
30 static constexpr bool ImplicitlyDetaches = false;
31 using Type = T;
32 using pointer = T *;
33 // for const-qualified functions:
34 using constT = T;
35};
36}
37
39{
40public:
41 mutable QAtomicInt ref;
42
43 QSharedData() noexcept : ref(0) { }
44 QSharedData(const QSharedData &) noexcept : ref(0) { }
45
46 // using the assignment operator would lead to corruption in the ref-counting
47 QSharedData &operator=(const QSharedData &) = delete;
48 ~QSharedData() = default;
49};
50
51struct QAdoptSharedDataTag { explicit constexpr QAdoptSharedDataTag() = default; };
52
53// CRTP common base class for both QSharedDataPointer and QExplicitlySharedDataPointer
54template <template <typename> class P, typename T> class QSharedDataPointerBase
55{
56#ifndef Q_QDOC
57 using Self = P<T>;
59 using constT = typename Traits::constT;
60
61protected:
62 constexpr QSharedDataPointerBase(T *ptr = nullptr) noexcept : d(ptr) {}
64
65public:
66 // When adding anything public to this class, make sure to add the doc version to
67 // both QSharedDataPointer and QExplicitlySharedDataPointer.
68
69 using Type = T;
70 using pointer = T *;
71
72 void detach() { if (d && d->ref.loadRelaxed() != 1) detach_helper(); }
73 T &operator*() { detachIfImplicit(); return *(d.get()); }
74 constT &operator*() const { return *(d.get()); }
75 T *operator->() { detachIfImplicit(); return d.get(); }
76 constT *operator->() const noexcept { return d.get(); }
77 operator T *() { detachIfImplicit(); return d.get(); }
78 operator const T *() const noexcept { return d.get(); }
79 T *data() { detachIfImplicit(); return d.get(); }
80 T *get() { detachIfImplicit(); return d.get(); }
81 const T *data() const noexcept { return d.get(); }
82 const T *get() const noexcept { return d.get(); }
83 const T *constData() const noexcept { return d.get(); }
84 T *take() noexcept { return std::exchange(d, nullptr).get(); }
85
86 void reset(T *ptr = nullptr) noexcept
87 {
88 if (ptr != d.get()) {
89 if (ptr)
90 ptr->ref.ref();
91 T *old = std::exchange(d, Qt::totally_ordered_wrapper(ptr)).get();
92 if (old && !old->ref.deref())
93 destroy(old);
94 }
95 }
96
97 operator bool () const noexcept { return d != nullptr; }
98 bool operator!() const noexcept { return d == nullptr; }
99
100 void swap(Self &other) noexcept
101 { qt_ptr_swap(d, other.d); }
102
103private:
104 // The concrete class MUST override these, otherwise we will be calling
105 // ourselves.
106 T *clone() { return static_cast<Self *>(this)->clone(); }
107 template <typename... Args> static T *create(Args &&... args)
108 { return Self::create(std::forward(args)...); }
109 static void destroy(T *ptr) { Self::destroy(ptr); }
110
111 void detachIfImplicit()
112 {
113 if constexpr (Traits::ImplicitlyDetaches)
114 static_cast<Self *>(this)->detach();
115 }
116
117 friend bool comparesEqual(const QSharedDataPointerBase &lhs, const QSharedDataPointerBase &rhs) noexcept
118 { return lhs.d == rhs.d; }
119 friend Qt::strong_ordering
121 { return Qt::compareThreeWay(lhs.d, rhs.d); }
122
123 friend bool comparesEqual(const QSharedDataPointerBase &lhs, const T *rhs) noexcept
124 { return lhs.d == rhs; }
125 friend Qt::strong_ordering
126 compareThreeWay(const QSharedDataPointerBase &lhs, const T *rhs) noexcept
127 { return Qt::compareThreeWay(lhs.d, rhs); }
128
129 friend bool comparesEqual(const QSharedDataPointerBase &lhs, std::nullptr_t) noexcept
130 { return lhs.d == nullptr; }
131 friend Qt::strong_ordering
132 compareThreeWay(const QSharedDataPointerBase &lhs, std::nullptr_t) noexcept
133 { return Qt::compareThreeWay(lhs.d, nullptr); }
134
135 friend size_t qHash(const QSharedDataPointerBase &ptr, size_t seed = 0) noexcept
136 { return qHash(ptr.data(), seed); }
137
138protected:
140
142#endif // !Q_QDOC
143};
144
145template <typename T>
146class QSharedDataPointer : public QSharedDataPointerBase<QSharedDataPointer, T>
147{
148 using Base = QSharedDataPointerBase<QSharedDataPointer, T>;
149 friend Base;
150public:
151 typedef T Type;
152 typedef T *pointer;
153
154 void detach() { Base::detach(); }
155#ifdef Q_QDOC
156 T &operator*();
157 const T &operator*() const;
158 T *operator->();
159 const T *operator->() const noexcept;
160 operator T *();
161 operator const T *() const noexcept;
162 T *data();
163 T *get();
164 const T *data() const noexcept;
165 const T *get() const noexcept;
166 const T *constData() const noexcept;
167 T *take() noexcept;
168#endif
169
170 Q_NODISCARD_CTOR
171 QSharedDataPointer() noexcept : Base(nullptr) { }
172 ~QSharedDataPointer() { if (d && !d->ref.deref()) destroy(d.get()); }
173
174 Q_NODISCARD_CTOR
175 explicit QSharedDataPointer(T *data) noexcept : Base(data)
176 { if (d) d->ref.ref(); }
177 Q_NODISCARD_CTOR
178 QSharedDataPointer(T *data, QAdoptSharedDataTag) noexcept : Base(data)
179 {}
180 Q_NODISCARD_CTOR
181 QSharedDataPointer(const QSharedDataPointer &o) noexcept : Base(o.d.get())
182 { if (d) d->ref.ref(); }
183
184 QSharedDataPointer &operator=(const QSharedDataPointer &o) noexcept
185 {
186 reset(o.d.get());
187 return *this;
188 }
189 inline QSharedDataPointer &operator=(T *o) noexcept
190 {
191 reset(o);
192 return *this;
193 }
194 Q_NODISCARD_CTOR
195 QSharedDataPointer(QSharedDataPointer &&o) noexcept
196 : Base(std::exchange(o.d, nullptr).get())
197 {}
198 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QSharedDataPointer)
199
200#ifdef Q_QDOC
201 void reset(T *ptr = nullptr) noexcept;
202
203 operator bool () const noexcept;
204 bool operator!() const noexcept;
205
206 void swap(QSharedDataPointer &other) noexcept;
207#else
208 using Base::reset;
209 using Base::swap;
210#endif
211
212protected:
213 T *clone();
214 template <typename... Args> static T *create(Args &&... args)
215 { return new T(std::forward(args)...); }
216 static void destroy(T *ptr) { delete ptr; }
217
218private:
219 Q_DECLARE_STRONGLY_ORDERED(QSharedDataPointer)
220 Q_DECLARE_STRONGLY_ORDERED(QSharedDataPointer, T*)
221 Q_DECLARE_STRONGLY_ORDERED(QSharedDataPointer, std::nullptr_t)
222
223 using Base::d;
224};
225
226template <typename T>
228{
230 friend Base;
231public:
232 typedef T Type;
233 typedef T *pointer;
234
235 // override to make explicit. Can use explicit(!ImplicitlyShared) once we
236 // can depend on C++20.
237 explicit operator T *() { return d.get(); }
238 explicit operator const T *() const noexcept { return d.get(); }
239
240 // override to make const. There is no const(cond), but we could use
241 // requires(!ImplicitlyShared)
242 T *data() const noexcept { return d.get(); }
243 T *get() const noexcept { return d.get(); }
244
245#ifdef Q_QDOC
246 T &operator*() const;
247 T *operator->() noexcept;
248 T *operator->() const noexcept;
249 T *data() const noexcept;
250 T *get() const noexcept;
251 const T *constData() const noexcept;
252 T *take() noexcept;
253#endif
254
255 void detach() { Base::detach(); }
256
258 QExplicitlySharedDataPointer() noexcept : Base(nullptr) { }
259 ~QExplicitlySharedDataPointer() { if (d && !d->ref.deref()) delete d.get(); }
260
263 { if (d) d->ref.ref(); }
270
271 template<typename X>
274#ifdef QT_ENABLE_QEXPLICITLYSHAREDDATAPOINTER_STATICCAST
275#error This macro has been removed in Qt 6.9.
276#endif
277 : Base(o.data())
278 { if (d) d->ref.ref(); }
279
281 {
282 reset(o.d.get());
283 return *this;
284 }
286 {
287 reset(o);
288 return *this;
289 }
295
296#ifdef Q_QDOC
297 void reset(T *ptr = nullptr) noexcept;
298
299 operator bool () const noexcept;
300 bool operator!() const noexcept;
301
303#else
304 using Base::swap;
305 using Base::reset;
306#endif
307
308protected:
309 T *clone();
310 template <typename... Args> static T *create(Args &&... args)
311 { return new T(std::forward(args)...); }
312 static void destroy(T *ptr) { delete ptr; }
313
314private:
318
319 using Base::d;
320};
321
322// Declared here and as Q_OUTOFLINE_TEMPLATE to work-around MSVC bug causing missing symbols at link time.
323template <typename T>
324Q_INLINE_TEMPLATE T *QSharedDataPointer<T>::clone()
325{
326 return new T(*this->d);
327}
328
329template <typename T>
330Q_INLINE_TEMPLATE T *QExplicitlySharedDataPointer<T>::clone()
331{
332 return new T(*this->d.get());
333}
334
335template <template <typename> class P, typename T> Q_OUTOFLINE_TEMPLATE void
336QSharedDataPointerBase<P, T>::detach_helper()
337{
338 T *x = clone();
339 x->ref.ref();
340 if (!d->ref.deref())
341 destroy(d.get());
342 d.reset(x);
343}
344
345template <typename T>
346void swap(QSharedDataPointer<T> &p1, QSharedDataPointer<T> &p2) noexcept
347{ p1.swap(p2); }
348
349template <typename T>
351{ p1.swap(p2); }
352
353template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedDataPointer<T>, Q_RELOCATABLE_TYPE);
355
356#define QT_DECLARE_QSDP_SPECIALIZATION_DTOR(Class)
357 template<> QSharedDataPointer<Class>::~QSharedDataPointer();
358
359#define QT_DECLARE_QSDP_SPECIALIZATION_DTOR_WITH_EXPORT(Class, ExportMacro)
360 template<> ExportMacro QSharedDataPointer<Class>::~QSharedDataPointer();
361
362#define QT_DEFINE_QSDP_SPECIALIZATION_DTOR(Class)
363 template<> QSharedDataPointer<Class>::~QSharedDataPointer()
364 {
365 if (d && !d->ref.deref())
366 delete d.get();
367 }
368
369#define QT_DECLARE_QESDP_SPECIALIZATION_DTOR(Class)
370 template<> QExplicitlySharedDataPointer<Class>::~QExplicitlySharedDataPointer();
371
372#define QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(Class, ExportMacro)
373 template<> ExportMacro QExplicitlySharedDataPointer<Class>::~QExplicitlySharedDataPointer();
374
375#define QT_DEFINE_QESDP_SPECIALIZATION_DTOR(Class)
376 template<> QExplicitlySharedDataPointer<Class>::~QExplicitlySharedDataPointer()
377 {
378 if (d && !d->ref.deref())
379 delete d.get();
380 }
381
382QT_END_NAMESPACE
383
384#endif // QSHAREDDATA_H
\inmodule QtCore
Definition qatomic.h:114
constexpr QAtomicInt(int value=0) noexcept
Constructs a QAtomicInt with the given value.
Definition qatomic.h:119
\macro Q_ATOMIC_INTnn_IS_SUPPORTED
Definition qatomic.h:125
QAtomicPointer(const QAtomicPointer< T > &other) noexcept
Constructs a copy of other.
Definition qatomic.h:129
QAtomicPointer< T > & operator=(const QAtomicPointer< T > &other) noexcept
Assigns other to this QAtomicPointer and returns a reference to this QAtomicPointer.
Definition qatomic.h:135
constexpr QAtomicPointer(T *value=nullptr) noexcept
Constructs a QAtomicPointer with the given value.
Definition qatomic.h:127
T * get() const noexcept
~QExplicitlySharedDataPointer()
Decrements the reference count of the shared data object.
static void destroy(T *ptr)
operator const T *() const noexcept
T Type
This is the type of the shared data object.
static T * create(Args &&... args)
QExplicitlySharedDataPointer & operator=(const QExplicitlySharedDataPointer &o) noexcept
Sets the {d pointer} of this to the {d pointer} of o and increments the reference count of the shared...
T * data() const noexcept
Returns a pointer to the shared data object.
void detach()
If the shared data object's reference count is greater than 1, this function creates a deep copy of t...
QExplicitlySharedDataPointer & operator=(T *o) noexcept
Sets the {d pointer} of this to o and increments {o}'s reference count.
QFileInfoPrivate(const QFileSystemEntry &file, const QFileSystemMetaData &data, std::unique_ptr< QAbstractFileEngine > engine)
Definition qfileinfo_p.h:98
bool const isDefaultConstructed
QFileInfoPrivate(const QFileSystemEntry &file, const QFileSystemMetaData &data)
Definition qfileinfo_p.h:83
Ret checkAttribute(QFileSystemMetaData::MetaDataFlags fsFlags, FSLambda fsLambda, EngineLambda engineLambda) const
QFileSystemMetaData metaData
QDateTime & getFileTime(QFile::FileTime) const
std::unique_ptr< QAbstractFileEngine > const fileEngine
QDateTime fileTimes[4]
uint getFileFlags(QAbstractFileEngine::FileFlags) const
void clearFlags() const
void setCachedFlag(uint c) const
QString getFileOwner(QAbstractFileEngine::FileOwner own) const
Definition qfileinfo.cpp:76
QString fileOwners[2]
bool getCachedFlag(uint c) const
QFileInfoPrivate(const QFileInfoPrivate &copy)
Definition qfileinfo_p.h:57
QFileSystemEntry fileEntry
static QFileInfoPrivate * get(QFileInfo *fi)
Definition qfileinfo_p.h:49
QString getFileName(QAbstractFileEngine::FileName) const
Definition qfileinfo.cpp:18
QString fileNames[QAbstractFileEngine::NFileNames]
QFileInfoPrivate(const QString &file)
Definition qfileinfo_p.h:70
Ret checkAttribute(Ret defaultValue, QFileSystemMetaData::MetaDataFlags fsFlags, FSLambda fsLambda, EngineLambda engineLambda) const
Qt::totally_ordered_wrapper< T * > d
constexpr QSharedDataPointerBase(T *ptr=nullptr) noexcept
Definition qshareddata.h:62
friend bool comparesEqual(const QSharedDataPointerBase &lhs, const T *rhs) noexcept
friend bool comparesEqual(const QSharedDataPointerBase &lhs, std::nullptr_t) noexcept
T * take() noexcept
Definition qshareddata.h:84
void reset(T *ptr=nullptr) noexcept
Definition qshareddata.h:86
const T * data() const noexcept
Definition qshareddata.h:81
void swap(Self &other) noexcept
bool operator!() const noexcept
Definition qshareddata.h:98
friend Qt::strong_ordering compareThreeWay(const QSharedDataPointerBase &lhs, const QSharedDataPointerBase &rhs) noexcept
friend Qt::strong_ordering compareThreeWay(const QSharedDataPointerBase &lhs, const T *rhs) noexcept
friend size_t qHash(const QSharedDataPointerBase &ptr, size_t seed=0) noexcept
constT & operator*() const
Definition qshareddata.h:74
constT * operator->() const noexcept
Definition qshareddata.h:76
friend bool comparesEqual(const QSharedDataPointerBase &lhs, const QSharedDataPointerBase &rhs) noexcept
const T * get() const noexcept
Definition qshareddata.h:82
operator bool() const noexcept
Definition qshareddata.h:97
friend Qt::strong_ordering compareThreeWay(const QSharedDataPointerBase &lhs, std::nullptr_t) noexcept
operator const T *() const noexcept
Definition qshareddata.h:78
const T * constData() const noexcept
Definition qshareddata.h:83
T Type
This is the type of the shared data object.
~QSharedDataPointer()
Decrements the reference count of the shared data object.
QSharedDataPointer & operator=(const QSharedDataPointer &o) noexcept
Sets the {d pointer} of this to the {d pointer} of o and increments the reference count of the shared...
static void destroy(T *ptr)
static T * create(Args &&... args)
void detach()
If the shared data object's reference count is greater than 1, this function creates a deep copy of t...
QSharedDataPointer & operator=(T *o) noexcept
Sets the {d pointer} og this to o and increments {o}'s reference count.
\inmodule QtCore
Definition qshareddata.h:39
QSharedData() noexcept
Constructs a QSharedData object with a reference count of 0.
Definition qshareddata.h:43
~QSharedData()=default
QAtomicInt ref
Definition qshareddata.h:41
QSharedData & operator=(const QSharedData &)=delete
QSharedData(const QSharedData &) noexcept
Constructs a QSharedData object with reference count 0.
Definition qshareddata.h:44
Combined button and popup list for selecting options.
void qAtomicDetach(T *&d)
This is a helper for the detach method of implicitly shared classes.
Definition qatomic.h:206
QDebug operator<<(QDebug dbg, const QFileInfo &fi)
bool comparesEqual(const QFileInfo &lhs, const QFileInfo &rhs)
Q_DECLARE_TYPEINFO_BODY(QExplicitlySharedDataPointer< T >, Q_RELOCATABLE_TYPE)
void swap(QExplicitlySharedDataPointer< T > &p1, QExplicitlySharedDataPointer< T > &p2) noexcept
void swap(QSharedDataPointer< T > &p1, QSharedDataPointer< T > &p2) noexcept
Q_DECLARE_TYPEINFO_BODY(QSharedDataPointer< T >, Q_RELOCATABLE_TYPE)
\inmodule QtCore \threadsafe
Definition qshareddata.h:51