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
qqmlrefcount_p.h
Go to the documentation of this file.
1// Copyright (C) 2016 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
4
5#ifndef QQMLREFCOUNT_P_H
6#define QQMLREFCOUNT_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <QtCore/qglobal.h>
20#include <QtCore/qatomic.h>
21#include <private/qv4global_p.h>
22
23QT_BEGIN_NAMESPACE
24
25template <typename T>
26class QQmlRefCounted;
27
29{
31public:
32 inline QQmlRefCount();
33 inline void addref() const;
34 inline int count() const;
35
36private:
37 inline ~QQmlRefCount();
38 template <typename T> friend class QQmlRefCounted;
39
40private:
41 mutable QAtomicInt refCount;
42};
43
44template <typename T>
46{
47public:
48 inline void release() const;
49protected:
50 inline ~QQmlRefCounted();
51};
52
53template<class T>
55{
56public:
57 enum Mode {
60 };
65 inline ~QQmlRefPointer();
66
67 void swap(QQmlRefPointer &other) noexcept { qt_ptr_swap(o, other.o); }
68
69 inline QQmlRefPointer<T> &operator=(const QQmlRefPointer<T> &o);
70 inline QQmlRefPointer<T> &operator=(QQmlRefPointer<T> &&o) noexcept;
71
72 inline bool isNull() const { return !o; }
73
74 inline T* operator->() const { return o; }
75 inline T& operator*() const { return *o; }
76 explicit inline operator bool() const { return o != nullptr; }
77 inline T* data() const { return o; }
78
79 inline QQmlRefPointer<T> &adopt(T *);
80
81 inline T* take() { T *res = o; o = nullptr; return res; }
82
83 friend bool operator==(const QQmlRefPointer &a, const QQmlRefPointer &b) noexcept
84 {
85 return a.o == b.o;
86 }
87
88 friend bool operator!=(const QQmlRefPointer &a, const QQmlRefPointer &b) noexcept
89 {
90 return !(a == b);
91 }
92
93 friend size_t qHash(const QQmlRefPointer &v, size_t seed = 0) noexcept
94 {
95 return qHash(v.o, seed);
96 }
97
98 void reset(T *t = nullptr)
99 {
100 if (t == o)
101 return;
102 if (o)
103 o->release();
104 if (t)
105 t->addref();
106 o = t;
107 }
108
109private:
110 T *o;
111};
112
113namespace QQml {
114/*!
115 \internal
116 Creates a QQmlRefPointer which takes ownership of a newly constructed T.
117 T must derive from QQmlRefCounted<T> (as we rely on an initial refcount of _1_).
118 T will be constructed by forwarding \a args to its constructor.
119 */
120template <typename T, typename ...Args>
122{
123 static_assert(std::is_base_of_v<QQmlRefCount, T>);
124 return QQmlRefPointer<T>(new T(std::forward<Args>(args)...), QQmlRefPointer<T>::Adopt);
125}
126}
127
128template <typename T>
130
131QQmlRefCount::QQmlRefCount()
132: refCount(1)
133{
134}
135
136QQmlRefCount::~QQmlRefCount()
137{
138 Q_ASSERT(refCount.loadRelaxed() == 0);
139}
140
141void QQmlRefCount::addref() const
142{
143 Q_ASSERT(refCount.loadRelaxed() > 0);
144 refCount.ref();
145}
146
147template <typename T>
148void QQmlRefCounted<T>::release() const
149{
150 static_assert(std::is_base_of_v<QQmlRefCounted, T>,
151 "QQmlRefCounted<T> must be a base of T (CRTP)");
152 Q_ASSERT(refCount.loadRelaxed() > 0);
153 if (!refCount.deref())
154 delete static_cast<const T *>(this);
155}
156
157template <typename T>
159{
160 static_assert(std::is_final_v<T> || std::has_virtual_destructor_v<T>,
161 "T must either be marked final or have a virtual dtor, "
162 "lest release() runs into UB.");
163}
164
165int QQmlRefCount::count() const
166{
167 return refCount.loadRelaxed();
168}
169
170template<class T>
171QQmlRefPointer<T>::QQmlRefPointer() noexcept
172: o(nullptr)
173{
174}
175
176template<class T>
177QQmlRefPointer<T>::QQmlRefPointer(T *o, Mode m)
178: o(o)
179{
180 if (m == AddRef && o)
181 o->addref();
182}
183
184template<class T>
185QQmlRefPointer<T>::QQmlRefPointer(const QQmlRefPointer<T> &other)
186: o(other.o)
187{
188 if (o) o->addref();
189}
190
191template <class T>
192QQmlRefPointer<T>::QQmlRefPointer(QQmlRefPointer<T> &&other) noexcept
193 : o(other.take())
194{
195}
196
197template<class T>
199{
200 if (o) o->release();
201}
202
203template<class T>
205{
206 if (o == other.o)
207 return *this;
208 if (other.o)
209 other.o->addref();
210 if (o)
211 o->release();
212 o = other.o;
213 return *this;
214}
215
216template <class T>
218{
219 QQmlRefPointer<T> m(std::move(other));
220 swap(m);
221 return *this;
222}
223
224/*!
225Takes ownership of \a other. take() does *not* add a reference, as it assumes ownership
226of the callers reference of other.
227*/
228template<class T>
230{
231 if (o) o->release();
232 o = other;
233 return *this;
234}
235
236QT_END_NAMESPACE
237
238#endif // QQMLREFCOUNT_P_H
friend class QQmlRefCounted
void addref() const
int count() const
void release() const
T * data() const
T & operator*() const
void swap(QQmlRefPointer &other) noexcept
QQmlRefPointer< T > & operator=(const QQmlRefPointer< T > &o)
QQmlRefPointer< T > & operator=(QQmlRefPointer< T > &&o) noexcept
void reset(T *t=nullptr)
friend size_t qHash(const QQmlRefPointer &v, size_t seed=0) noexcept
QQmlRefPointer< T > & adopt(T *)
Takes ownership of other.
T * operator->() const
friend bool operator!=(const QQmlRefPointer &a, const QQmlRefPointer &b) noexcept
friend bool operator==(const QQmlRefPointer &a, const QQmlRefPointer &b) noexcept
bool isNull() const
operator bool() const
QQmlRefPointer< T > makeRefPointer(Args &&... args)
Q_DECLARE_TYPEINFO_BODY(QQmlRefPointer< T >, Q_RELOCATABLE_TYPE)