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