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) {}
63
64public:
65 // When adding anything public to this class, make sure to add the doc version to
66 // both QSharedDataPointer and QExplicitlySharedDataPointer.
67
68 using Type = T;
69 using pointer = T *;
70
71 void detach() { if (d && d->ref.loadRelaxed() != 1) detach_helper(); }
72 T &operator*() { implicitlyDetach(); return *(d.get()); }
73 constT &operator*() const { return *(d.get()); }
74 T *operator->() { implicitlyDetach(); return d.get(); }
75 constT *operator->() const noexcept { return d.get(); }
76 operator T *() { implicitlyDetach(); return d.get(); }
77 operator const T *() const noexcept { return d.get(); }
78 T *data() { implicitlyDetach(); return d.get(); }
79 T *get() { implicitlyDetach(); return d.get(); }
80 const T *data() const noexcept { return d.get(); }
81 const T *get() const noexcept { return d.get(); }
82 const T *constData() const noexcept { return d.get(); }
83 T *take() noexcept { return std::exchange(d, nullptr).get(); }
84
85 void reset(T *ptr = nullptr) noexcept
86 {
87 if (ptr != d.get()) {
88 if (ptr)
89 ptr->ref.ref();
90 T *old = std::exchange(d, Qt::totally_ordered_wrapper(ptr)).get();
91 if (old && !old->ref.deref())
92 destroy(old);
93 }
94 }
95
96 operator bool () const noexcept { return d != nullptr; }
97 bool operator!() const noexcept { return d == nullptr; }
98
99 void swap(Self &other) noexcept
100 { qt_ptr_swap(d, other.d); }
101
102private:
103 // The concrete class MUST override these, otherwise we will be calling
104 // ourselves.
105 T *clone() { return static_cast<Self *>(this)->clone(); }
106 template <typename... Args> static T *create(Args &&... args)
107 { return Self::create(std::forward(args)...); }
108 static void destroy(T *ptr) { Self::destroy(ptr); }
109
110 void implicitlyDetach()
111 {
112 if constexpr (Traits::ImplicitlyDetaches)
113 static_cast<Self *>(this)->detach();
114 }
115
116 friend bool comparesEqual(const QSharedDataPointerBase &lhs, const QSharedDataPointerBase &rhs) noexcept
117 { return lhs.d == rhs.d; }
118 friend Qt::strong_ordering
120 { return Qt::compareThreeWay(lhs.d, rhs.d); }
121
122 friend bool comparesEqual(const QSharedDataPointerBase &lhs, const T *rhs) noexcept
123 { return lhs.d == rhs; }
124 friend Qt::strong_ordering
125 compareThreeWay(const QSharedDataPointerBase &lhs, const T *rhs) noexcept
126 { return Qt::compareThreeWay(lhs.d, rhs); }
127
128 friend bool comparesEqual(const QSharedDataPointerBase &lhs, std::nullptr_t) noexcept
129 { return lhs.d == nullptr; }
130 friend Qt::strong_ordering
131 compareThreeWay(const QSharedDataPointerBase &lhs, std::nullptr_t) noexcept
132 { return Qt::compareThreeWay(lhs.d, nullptr); }
133
134 friend size_t qHash(const QSharedDataPointerBase &ptr, size_t seed = 0) noexcept
135 { return qHash(ptr.data(), seed); }
136
137protected:
139
141#endif // !Q_QDOC
142};
143
144template <typename T>
145class QSharedDataPointer : public QSharedDataPointerBase<QSharedDataPointer, T>
146{
147 using Base = QSharedDataPointerBase<QSharedDataPointer, T>;
148 friend Base;
149public:
150 typedef T Type;
151 typedef T *pointer;
152
153 void detach() { Base::detach(); }
154#ifdef Q_QDOC
155 T &operator*();
156 const T &operator*() const;
157 T *operator->();
158 const T *operator->() const noexcept;
159 operator T *();
160 operator const T *() const noexcept;
161 T *data();
162 T *get();
163 const T *data() const noexcept;
164 const T *get() const noexcept;
165 const T *constData() const noexcept;
166 T *take() noexcept;
167#endif
168
169 Q_NODISCARD_CTOR
170 QSharedDataPointer() noexcept : Base(nullptr) { }
171 ~QSharedDataPointer() { if (d && !d->ref.deref()) destroy(d.get()); }
172
173 Q_NODISCARD_CTOR
174 explicit QSharedDataPointer(T *data) noexcept : Base(data)
175 { if (d) d->ref.ref(); }
176 Q_NODISCARD_CTOR
177 QSharedDataPointer(T *data, QAdoptSharedDataTag) noexcept : Base(data)
178 {}
179 Q_NODISCARD_CTOR
180 QSharedDataPointer(const QSharedDataPointer &o) noexcept : Base(o.d.get())
181 { if (d) d->ref.ref(); }
182
183 QSharedDataPointer &operator=(const QSharedDataPointer &o) noexcept
184 {
185 reset(o.d.get());
186 return *this;
187 }
188 inline QSharedDataPointer &operator=(T *o) noexcept
189 {
190 reset(o);
191 return *this;
192 }
193 Q_NODISCARD_CTOR
194 QSharedDataPointer(QSharedDataPointer &&o) noexcept
195 : Base(std::exchange(o.d, nullptr).get())
196 {}
197 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QSharedDataPointer)
198
199#ifdef Q_QDOC
200 void reset(T *ptr = nullptr) noexcept;
201
202 operator bool () const noexcept;
203 bool operator!() const noexcept;
204
205 void swap(QSharedDataPointer &other) noexcept;
206#else
207 using Base::reset;
208 using Base::swap;
209#endif
210
211protected:
212 T *clone();
213 template <typename... Args> static T *create(Args &&... args)
214 { return new T(std::forward(args)...); }
215 static void destroy(T *ptr) { delete ptr; }
216
217private:
218 Q_DECLARE_STRONGLY_ORDERED(QSharedDataPointer)
219 Q_DECLARE_STRONGLY_ORDERED(QSharedDataPointer, T*)
220 Q_DECLARE_STRONGLY_ORDERED(QSharedDataPointer, std::nullptr_t)
221
222 using Base::d;
223};
224
225template <typename T>
227{
229 friend Base;
230public:
231 typedef T Type;
232 typedef T *pointer;
233
234 // override to make explicit. Can use explicit(!ImplicitlyShared) once we
235 // can depend on C++20.
236 explicit operator T *() { return d.get(); }
237 explicit operator const T *() const noexcept { return d.get(); }
238
239 // override to make const. There is no const(cond), but we could use
240 // requires(!ImplicitlyShared)
241 T *data() const noexcept { return d.get(); }
242 T *get() const noexcept { return d.get(); }
243
244#ifdef Q_QDOC
245 T &operator*() const;
246 T *operator->() noexcept;
247 T *operator->() const noexcept;
248 T *data() const noexcept;
249 T *get() const noexcept;
250 const T *constData() const noexcept;
251 T *take() noexcept;
252#endif
253
254 void detach() { Base::detach(); }
255
257 QExplicitlySharedDataPointer() noexcept : Base(nullptr) { }
258 ~QExplicitlySharedDataPointer() { if (d && !d->ref.deref()) delete d.get(); }
259
262 { if (d) d->ref.ref(); }
269
270 template<typename X>
273#ifdef QT_ENABLE_QEXPLICITLYSHAREDDATAPOINTER_STATICCAST
274#error This macro has been removed in Qt 6.9.
275#endif
276 : Base(o.data())
277 { if (d) d->ref.ref(); }
278
280 {
281 reset(o.d.get());
282 return *this;
283 }
285 {
286 reset(o);
287 return *this;
288 }
294
295#ifdef Q_QDOC
296 void reset(T *ptr = nullptr) noexcept;
297
298 operator bool () const noexcept;
299 bool operator!() const noexcept;
300
302#else
303 using Base::swap;
304 using Base::reset;
305#endif
306
307protected:
308 T *clone();
309 template <typename... Args> static T *create(Args &&... args)
310 { return new T(std::forward(args)...); }
311 static void destroy(T *ptr) { delete ptr; }
312
313private:
317
318 using Base::d;
319};
320
321// Declared here and as Q_OUTOFLINE_TEMPLATE to work-around MSVC bug causing missing symbols at link time.
322template <typename T>
323Q_INLINE_TEMPLATE T *QSharedDataPointer<T>::clone()
324{
325 return new T(*this->d);
326}
327
328template <typename T>
329Q_INLINE_TEMPLATE T *QExplicitlySharedDataPointer<T>::clone()
330{
331 return new T(*this->d.get());
332}
333
334template <template <typename> class P, typename T> Q_OUTOFLINE_TEMPLATE void
335QSharedDataPointerBase<P, T>::detach_helper()
336{
337 T *x = clone();
338 x->ref.ref();
339 if (!d->ref.deref())
340 delete d.get();
341 d.reset(x);
342}
343
344template <typename T>
345void swap(QSharedDataPointer<T> &p1, QSharedDataPointer<T> &p2) noexcept
346{ p1.swap(p2); }
347
348template <typename T>
350{ p1.swap(p2); }
351
352template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedDataPointer<T>, Q_RELOCATABLE_TYPE);
354
355#define QT_DECLARE_QSDP_SPECIALIZATION_DTOR(Class)
356 template<> QSharedDataPointer<Class>::~QSharedDataPointer();
357
358#define QT_DECLARE_QSDP_SPECIALIZATION_DTOR_WITH_EXPORT(Class, ExportMacro)
359 template<> ExportMacro QSharedDataPointer<Class>::~QSharedDataPointer();
360
361#define QT_DEFINE_QSDP_SPECIALIZATION_DTOR(Class)
362 template<> QSharedDataPointer<Class>::~QSharedDataPointer()
363 {
364 if (d && !d->ref.deref())
365 delete d.get();
366 }
367
368#define QT_DECLARE_QESDP_SPECIALIZATION_DTOR(Class)
369 template<> QExplicitlySharedDataPointer<Class>::~QExplicitlySharedDataPointer();
370
371#define QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(Class, ExportMacro)
372 template<> ExportMacro QExplicitlySharedDataPointer<Class>::~QExplicitlySharedDataPointer();
373
374#define QT_DEFINE_QESDP_SPECIALIZATION_DTOR(Class)
375 template<> QExplicitlySharedDataPointer<Class>::~QExplicitlySharedDataPointer()
376 {
377 if (d && !d->ref.deref())
378 delete d.get();
379 }
380
381QT_END_NAMESPACE
382
383#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:83
void reset(T *ptr=nullptr) noexcept
Definition qshareddata.h:85
const T * data() const noexcept
Definition qshareddata.h:80
void swap(Self &other) noexcept
Definition qshareddata.h:99
bool operator!() const noexcept
Definition qshareddata.h:97
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:73
constT * operator->() const noexcept
Definition qshareddata.h:75
friend bool comparesEqual(const QSharedDataPointerBase &lhs, const QSharedDataPointerBase &rhs) noexcept
const T * get() const noexcept
Definition qshareddata.h:81
operator bool() const noexcept
Definition qshareddata.h:96
friend Qt::strong_ordering compareThreeWay(const QSharedDataPointerBase &lhs, std::nullptr_t) noexcept
operator const T *() const noexcept
Definition qshareddata.h:77
const T * constData() const noexcept
Definition qshareddata.h:82
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:201
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