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
4#ifndef QSHAREDDATA_H
5#define QSHAREDDATA_H
6
7#include <QtCore/qatomic.h>
8#include <QtCore/qcompare.h>
9#include <QtCore/qhashfunctions.h>
10
12
13template <class T> class QSharedDataPointer;
14template <class T> class QExplicitlySharedDataPointer;
15
16namespace QtPrivate {
17template <template <typename> class P, typename T> struct QSharedDataPointerTraits;
18template <typename T> struct QSharedDataPointerTraits<QSharedDataPointer, T>
19{
20 static constexpr bool ImplicitlyDetaches = true;
21 using Type = T;
22 using pointer = T *;
23 // for const-qualified functions:
24 using constT = const T;
25};
26
28{
29 static constexpr bool ImplicitlyDetaches = false;
30 using Type = T;
31 using pointer = T *;
32 // for const-qualified functions:
33 using constT = T;
34};
35}
36
38{
39public:
40 mutable QAtomicInt ref;
41
42 QSharedData() noexcept : ref(0) { }
43 QSharedData(const QSharedData &) noexcept : ref(0) { }
44
45 // using the assignment operator would lead to corruption in the ref-counting
46 QSharedData &operator=(const QSharedData &) = delete;
47 ~QSharedData() = default;
48};
49
50struct QAdoptSharedDataTag { explicit constexpr QAdoptSharedDataTag() = default; };
51
52// CRTP common base class for both QSharedDataPointer and QExplicitlySharedDataPointer
53template <template <typename> class P, typename T> class QSharedDataPointerBase
54{
55#ifndef Q_QDOC
56 using Self = P<T>;
58 using constT = typename Traits::constT;
59
60protected:
61 constexpr QSharedDataPointerBase(T *ptr = nullptr) noexcept : d(ptr) {}
62
63public:
64 // When adding anything public to this class, make sure to add the doc version to
65 // both QSharedDataPointer and QExplicitlySharedDataPointer.
66
67 using Type = T;
68 using pointer = T *;
69
70 void detach() { if (d && d->ref.loadRelaxed() != 1) detach_helper(); }
71 T &operator*() { implicitlyDetach(); return *(d.get()); }
72 constT &operator*() const { return *(d.get()); }
73 T *operator->() { implicitlyDetach(); return d.get(); }
74 constT *operator->() const noexcept { return d.get(); }
75 operator T *() { implicitlyDetach(); return d.get(); }
76 operator const T *() const noexcept { return d.get(); }
77 T *data() { implicitlyDetach(); return d.get(); }
78 T *get() { implicitlyDetach(); return d.get(); }
79 const T *data() const noexcept { return d.get(); }
80 const T *get() const noexcept { return d.get(); }
81 const T *constData() const noexcept { return d.get(); }
82 T *take() noexcept { return std::exchange(d, nullptr).get(); }
83
84 void reset(T *ptr = nullptr) noexcept
85 {
86 if (ptr != d.get()) {
87 if (ptr)
88 ptr->ref.ref();
89 T *old = std::exchange(d, Qt::totally_ordered_wrapper(ptr)).get();
90 if (old && !old->ref.deref())
91 destroy(old);
92 }
93 }
94
95 operator bool () const noexcept { return d != nullptr; }
96 bool operator!() const noexcept { return d == nullptr; }
97
98 void swap(Self &other) noexcept
99 { qt_ptr_swap(d, other.d); }
100
101private:
102 // The concrete class MUST override these, otherwise we will be calling
103 // ourselves.
104 T *clone() { return static_cast<Self *>(this)->clone(); }
105 template <typename... Args> static T *create(Args &&... args)
106 { return Self::create(std::forward(args)...); }
107 static void destroy(T *ptr) { Self::destroy(ptr); }
108
109 void implicitlyDetach()
110 {
111 if constexpr (Traits::ImplicitlyDetaches)
112 static_cast<Self *>(this)->detach();
113 }
114
115 friend bool comparesEqual(const QSharedDataPointerBase &lhs, const QSharedDataPointerBase &rhs) noexcept
116 { return lhs.d == rhs.d; }
117 friend Qt::strong_ordering
119 { return Qt::compareThreeWay(lhs.d, rhs.d); }
120
121 friend bool comparesEqual(const QSharedDataPointerBase &lhs, const T *rhs) noexcept
122 { return lhs.d == rhs; }
123 friend Qt::strong_ordering
124 compareThreeWay(const QSharedDataPointerBase &lhs, const T *rhs) noexcept
125 { return Qt::compareThreeWay(lhs.d, rhs); }
126
127 friend bool comparesEqual(const QSharedDataPointerBase &lhs, std::nullptr_t) noexcept
128 { return lhs.d == nullptr; }
129 friend Qt::strong_ordering
130 compareThreeWay(const QSharedDataPointerBase &lhs, std::nullptr_t) noexcept
131 { return Qt::compareThreeWay(lhs.d, nullptr); }
132
133 friend size_t qHash(const QSharedDataPointerBase &ptr, size_t seed = 0) noexcept
134 { return qHash(ptr.data(), seed); }
135
136protected:
138
140#endif // !Q_QDOC
141};
142
143template <typename T>
144class QSharedDataPointer : public QSharedDataPointerBase<QSharedDataPointer, T>
145{
146 using Base = QSharedDataPointerBase<QSharedDataPointer, T>;
147 friend Base;
148public:
149 typedef T Type;
150 typedef T *pointer;
151
152 void detach() { Base::detach(); }
153#ifdef Q_QDOC
154 T &operator*();
155 const T &operator*() const;
156 T *operator->();
157 const T *operator->() const noexcept;
158 operator T *();
159 operator const T *() const noexcept;
160 T *data();
161 T *get();
162 const T *data() const noexcept;
163 const T *get() const noexcept;
164 const T *constData() const noexcept;
165 T *take() noexcept;
166#endif
167
168 Q_NODISCARD_CTOR
169 QSharedDataPointer() noexcept : Base(nullptr) { }
170 ~QSharedDataPointer() { if (d && !d->ref.deref()) destroy(d.get()); }
171
172 Q_NODISCARD_CTOR
173 explicit QSharedDataPointer(T *data) noexcept : Base(data)
174 { if (d) d->ref.ref(); }
175 Q_NODISCARD_CTOR
176 QSharedDataPointer(T *data, QAdoptSharedDataTag) noexcept : Base(data)
177 {}
178 Q_NODISCARD_CTOR
179 QSharedDataPointer(const QSharedDataPointer &o) noexcept : Base(o.d.get())
180 { if (d) d->ref.ref(); }
181
182 QSharedDataPointer &operator=(const QSharedDataPointer &o) noexcept
183 {
184 reset(o.d.get());
185 return *this;
186 }
187 inline QSharedDataPointer &operator=(T *o) noexcept
188 {
189 reset(o);
190 return *this;
191 }
192 Q_NODISCARD_CTOR
193 QSharedDataPointer(QSharedDataPointer &&o) noexcept
194 : Base(std::exchange(o.d, nullptr).get())
195 {}
196 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QSharedDataPointer)
197
198#ifdef Q_QDOC
199 void reset(T *ptr = nullptr) noexcept;
200
201 operator bool () const noexcept;
202 bool operator!() const noexcept;
203
204 void swap(QSharedDataPointer &other) noexcept;
205#else
206 using Base::reset;
207 using Base::swap;
208#endif
209
210protected:
211 T *clone();
212 template <typename... Args> static T *create(Args &&... args)
213 { return new T(std::forward(args)...); }
214 static void destroy(T *ptr) { delete ptr; }
215
216private:
217 Q_DECLARE_STRONGLY_ORDERED(QSharedDataPointer)
218 Q_DECLARE_STRONGLY_ORDERED(QSharedDataPointer, T*)
219 Q_DECLARE_STRONGLY_ORDERED(QSharedDataPointer, std::nullptr_t)
220
221 using Base::d;
222};
223
224template <typename T>
226{
228 friend Base;
229public:
230 typedef T Type;
231 typedef T *pointer;
232
233 // override to make explicit. Can use explicit(!ImplicitlyShared) once we
234 // can depend on C++20.
235 explicit operator T *() { return d.get(); }
236 explicit operator const T *() const noexcept { return d.get(); }
237
238 // override to make const. There is no const(cond), but we could use
239 // requires(!ImplicitlyShared)
240 T *data() const noexcept { return d.get(); }
241 T *get() const noexcept { return d.get(); }
242
243#ifdef Q_QDOC
244 T &operator*() const;
245 T *operator->() noexcept;
246 T *operator->() const noexcept;
247 T *data() const noexcept;
248 T *get() const noexcept;
249 const T *constData() const noexcept;
250 T *take() noexcept;
251#endif
252
253 void detach() { Base::detach(); }
254
256 QExplicitlySharedDataPointer() noexcept : Base(nullptr) { }
257 ~QExplicitlySharedDataPointer() { if (d && !d->ref.deref()) delete d.get(); }
258
261 { if (d) d->ref.ref(); }
268
269 template<typename X>
272#ifdef QT_ENABLE_QEXPLICITLYSHAREDDATAPOINTER_STATICCAST
273#error This macro has been removed in Qt 6.9.
274#endif
275 : Base(o.data())
276 { if (d) d->ref.ref(); }
277
279 {
280 reset(o.d.get());
281 return *this;
282 }
284 {
285 reset(o);
286 return *this;
287 }
293
294#ifdef Q_QDOC
295 void reset(T *ptr = nullptr) noexcept;
296
297 operator bool () const noexcept;
298 bool operator!() const noexcept;
299
301#else
302 using Base::swap;
303 using Base::reset;
304#endif
305
306protected:
307 T *clone();
308 template <typename... Args> static T *create(Args &&... args)
309 { return new T(std::forward(args)...); }
310 static void destroy(T *ptr) { delete ptr; }
311
312private:
316
317 using Base::d;
318};
319
320// Declared here and as Q_OUTOFLINE_TEMPLATE to work-around MSVC bug causing missing symbols at link time.
321template <typename T>
322Q_INLINE_TEMPLATE T *QSharedDataPointer<T>::clone()
323{
324 return new T(*this->d);
325}
326
327template <typename T>
328Q_INLINE_TEMPLATE T *QExplicitlySharedDataPointer<T>::clone()
329{
330 return new T(*this->d.get());
331}
332
333template <template <typename> class P, typename T> Q_OUTOFLINE_TEMPLATE void
334QSharedDataPointerBase<P, T>::detach_helper()
335{
336 T *x = clone();
337 x->ref.ref();
338 if (!d->ref.deref())
339 delete d.get();
340 d.reset(x);
341}
342
343template <typename T>
344void swap(QSharedDataPointer<T> &p1, QSharedDataPointer<T> &p2) noexcept
345{ p1.swap(p2); }
346
347template <typename T>
349{ p1.swap(p2); }
350
351template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedDataPointer<T>, Q_RELOCATABLE_TYPE);
353
354#define QT_DECLARE_QSDP_SPECIALIZATION_DTOR(Class)
355 template<> QSharedDataPointer<Class>::~QSharedDataPointer();
356
357#define QT_DECLARE_QSDP_SPECIALIZATION_DTOR_WITH_EXPORT(Class, ExportMacro)
358 template<> ExportMacro QSharedDataPointer<Class>::~QSharedDataPointer();
359
360#define QT_DEFINE_QSDP_SPECIALIZATION_DTOR(Class)
361 template<> QSharedDataPointer<Class>::~QSharedDataPointer()
362 {
363 if (d && !d->ref.deref())
364 delete d.get();
365 }
366
367#define QT_DECLARE_QESDP_SPECIALIZATION_DTOR(Class)
368 template<> QExplicitlySharedDataPointer<Class>::~QExplicitlySharedDataPointer();
369
370#define QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(Class, ExportMacro)
371 template<> ExportMacro QExplicitlySharedDataPointer<Class>::~QExplicitlySharedDataPointer();
372
373#define QT_DEFINE_QESDP_SPECIALIZATION_DTOR(Class)
374 template<> QExplicitlySharedDataPointer<Class>::~QExplicitlySharedDataPointer()
375 {
376 if (d && !d->ref.deref())
377 delete d.get();
378 }
379
380QT_END_NAMESPACE
381
382#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:61
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:82
void reset(T *ptr=nullptr) noexcept
Definition qshareddata.h:84
const T * data() const noexcept
Definition qshareddata.h:79
void swap(Self &other) noexcept
Definition qshareddata.h:98
bool operator!() const noexcept
Definition qshareddata.h:96
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:72
constT * operator->() const noexcept
Definition qshareddata.h:74
friend bool comparesEqual(const QSharedDataPointerBase &lhs, const QSharedDataPointerBase &rhs) noexcept
const T * get() const noexcept
Definition qshareddata.h:80
operator bool() const noexcept
Definition qshareddata.h:95
friend Qt::strong_ordering compareThreeWay(const QSharedDataPointerBase &lhs, std::nullptr_t) noexcept
operator const T *() const noexcept
Definition qshareddata.h:76
const T * constData() const noexcept
Definition qshareddata.h:81
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:38
QSharedData() noexcept
Constructs a QSharedData object with a reference count of 0.
Definition qshareddata.h:42
~QSharedData()=default
QAtomicInt ref
Definition qshareddata.h:40
QSharedData & operator=(const QSharedData &)=delete
QSharedData(const QSharedData &) noexcept
Constructs a QSharedData object with reference count 0.
Definition qshareddata.h:43
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:50