1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). |
4 | ** Contact: http://www.qt-project.org/legal |
5 | ** |
6 | ** This file is part of the QtCore module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and Digia. For licensing terms and |
14 | ** conditions see http://qt.digia.com/licensing. For further information |
15 | ** use the contact form at http://qt.digia.com/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 2.1 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 2.1 requirements |
23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
24 | ** |
25 | ** In addition, as a special exception, Digia gives you certain additional |
26 | ** rights. These rights are described in the Digia Qt LGPL Exception |
27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
28 | ** |
29 | ** GNU General Public License Usage |
30 | ** Alternatively, this file may be used under the terms of the GNU |
31 | ** General Public License version 3.0 as published by the Free Software |
32 | ** Foundation and appearing in the file LICENSE.GPL included in the |
33 | ** packaging of this file. Please review the following information to |
34 | ** ensure the GNU General Public License version 3.0 requirements will be |
35 | ** met: http://www.gnu.org/copyleft/gpl.html. |
36 | ** |
37 | ** |
38 | ** $QT_END_LICENSE$ |
39 | ** |
40 | ****************************************************************************/ |
41 | |
42 | #ifndef QSHAREDDATA_H |
43 | #define QSHAREDDATA_H |
44 | |
45 | #include <QtCore/qglobal.h> |
46 | #include <QtCore/qatomic.h> |
47 | |
48 | QT_BEGIN_HEADER |
49 | |
50 | QT_BEGIN_NAMESPACE |
51 | |
52 | QT_MODULE(Core) |
53 | |
54 | template <class T> class QSharedDataPointer; |
55 | |
56 | class Q_CORE_EXPORT QSharedData |
57 | { |
58 | public: |
59 | mutable QAtomicInt ref; |
60 | |
61 | inline QSharedData() : ref(0) { } |
62 | inline QSharedData(const QSharedData &) : ref(0) { } |
63 | |
64 | private: |
65 | // using the assignment operator would lead to corruption in the ref-counting |
66 | QSharedData &operator=(const QSharedData &); |
67 | }; |
68 | |
69 | template <class T> class QSharedDataPointer |
70 | { |
71 | public: |
72 | typedef T Type; |
73 | typedef T *pointer; |
74 | |
75 | inline void detach() { if (d && d->ref != 1) detach_helper(); } |
76 | inline T &operator*() { detach(); return *d; } |
77 | inline const T &operator*() const { return *d; } |
78 | inline T *operator->() { detach(); return d; } |
79 | inline const T *operator->() const { return d; } |
80 | inline operator T *() { detach(); return d; } |
81 | inline operator const T *() const { return d; } |
82 | inline T *data() { detach(); return d; } |
83 | inline const T *data() const { return d; } |
84 | inline const T *constData() const { return d; } |
85 | |
86 | inline bool operator==(const QSharedDataPointer<T> &other) const { return d == other.d; } |
87 | inline bool operator!=(const QSharedDataPointer<T> &other) const { return d != other.d; } |
88 | |
89 | inline QSharedDataPointer() { d = 0; } |
90 | inline ~QSharedDataPointer() { if (d && !d->ref.deref()) delete d; } |
91 | |
92 | explicit QSharedDataPointer(T *data); |
93 | inline QSharedDataPointer(const QSharedDataPointer<T> &o) : d(o.d) { if (d) d->ref.ref(); } |
94 | inline QSharedDataPointer<T> & operator=(const QSharedDataPointer<T> &o) { |
95 | if (o.d != d) { |
96 | if (o.d) |
97 | o.d->ref.ref(); |
98 | T *old = d; |
99 | d = o.d; |
100 | if (old && !old->ref.deref()) |
101 | delete old; |
102 | } |
103 | return *this; |
104 | } |
105 | inline QSharedDataPointer &operator=(T *o) { |
106 | if (o != d) { |
107 | if (o) |
108 | o->ref.ref(); |
109 | T *old = d; |
110 | d = o; |
111 | if (old && !old->ref.deref()) |
112 | delete old; |
113 | } |
114 | return *this; |
115 | } |
116 | #ifdef Q_COMPILER_RVALUE_REFS |
117 | QSharedDataPointer(QSharedDataPointer &&o) : d(o.d) { o.d = 0; } |
118 | inline QSharedDataPointer<T> &operator=(QSharedDataPointer<T> &&other) |
119 | { qSwap(d, other.d); return *this; } |
120 | #endif |
121 | |
122 | inline bool operator!() const { return !d; } |
123 | |
124 | inline void swap(QSharedDataPointer &other) |
125 | { qSwap(d, other.d); } |
126 | |
127 | protected: |
128 | T *clone(); |
129 | |
130 | private: |
131 | void detach_helper(); |
132 | |
133 | T *d; |
134 | }; |
135 | |
136 | template <class T> class QExplicitlySharedDataPointer |
137 | { |
138 | public: |
139 | typedef T Type; |
140 | typedef T *pointer; |
141 | |
142 | inline T &operator*() const { return *d; } |
143 | inline T *operator->() { return d; } |
144 | inline T *operator->() const { return d; } |
145 | inline T *data() const { return d; } |
146 | inline const T *constData() const { return d; } |
147 | |
148 | inline void detach() { if (d && d->ref != 1) detach_helper(); } |
149 | |
150 | inline void reset() |
151 | { |
152 | if(d && !d->ref.deref()) |
153 | delete d; |
154 | |
155 | d = 0; |
156 | } |
157 | |
158 | inline operator bool () const { return d != 0; } |
159 | |
160 | inline bool operator==(const QExplicitlySharedDataPointer<T> &other) const { return d == other.d; } |
161 | inline bool operator!=(const QExplicitlySharedDataPointer<T> &other) const { return d != other.d; } |
162 | inline bool operator==(const T *ptr) const { return d == ptr; } |
163 | inline bool operator!=(const T *ptr) const { return d != ptr; } |
164 | |
165 | inline QExplicitlySharedDataPointer() { d = 0; } |
166 | inline ~QExplicitlySharedDataPointer() { if (d && !d->ref.deref()) delete d; } |
167 | |
168 | explicit QExplicitlySharedDataPointer(T *data); |
169 | inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<T> &o) : d(o.d) { if (d) d->ref.ref(); } |
170 | |
171 | template<class X> |
172 | inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X> &o) : d(static_cast<T *>(o.data())) |
173 | { |
174 | if(d) |
175 | d->ref.ref(); |
176 | } |
177 | |
178 | inline QExplicitlySharedDataPointer<T> & operator=(const QExplicitlySharedDataPointer<T> &o) { |
179 | if (o.d != d) { |
180 | if (o.d) |
181 | o.d->ref.ref(); |
182 | T *old = d; |
183 | d = o.d; |
184 | if (old && !old->ref.deref()) |
185 | delete old; |
186 | } |
187 | return *this; |
188 | } |
189 | inline QExplicitlySharedDataPointer &operator=(T *o) { |
190 | if (o != d) { |
191 | if (o) |
192 | o->ref.ref(); |
193 | T *old = d; |
194 | d = o; |
195 | if (old && !old->ref.deref()) |
196 | delete old; |
197 | } |
198 | return *this; |
199 | } |
200 | #ifdef Q_COMPILER_RVALUE_REFS |
201 | inline QExplicitlySharedDataPointer(QExplicitlySharedDataPointer &&o) : d(o.d) { o.d = 0; } |
202 | inline QExplicitlySharedDataPointer<T> &operator=(QExplicitlySharedDataPointer<T> &&other) |
203 | { qSwap(d, other.d); return *this; } |
204 | #endif |
205 | |
206 | inline bool operator!() const { return !d; } |
207 | |
208 | inline void swap(QExplicitlySharedDataPointer &other) |
209 | { qSwap(d, other.d); } |
210 | |
211 | protected: |
212 | T *clone(); |
213 | |
214 | private: |
215 | void detach_helper(); |
216 | |
217 | T *d; |
218 | }; |
219 | |
220 | template <class T> |
221 | Q_INLINE_TEMPLATE QSharedDataPointer<T>::QSharedDataPointer(T *adata) : d(adata) |
222 | { if (d) d->ref.ref(); } |
223 | |
224 | template <class T> |
225 | Q_INLINE_TEMPLATE T *QSharedDataPointer<T>::clone() |
226 | { |
227 | return new T(*d); |
228 | } |
229 | |
230 | template <class T> |
231 | Q_OUTOFLINE_TEMPLATE void QSharedDataPointer<T>::detach_helper() |
232 | { |
233 | T *x = clone(); |
234 | x->ref.ref(); |
235 | if (!d->ref.deref()) |
236 | delete d; |
237 | d = x; |
238 | } |
239 | |
240 | template <class T> |
241 | Q_INLINE_TEMPLATE T *QExplicitlySharedDataPointer<T>::clone() |
242 | { |
243 | return new T(*d); |
244 | } |
245 | |
246 | template <class T> |
247 | Q_OUTOFLINE_TEMPLATE void QExplicitlySharedDataPointer<T>::detach_helper() |
248 | { |
249 | T *x = clone(); |
250 | x->ref.ref(); |
251 | if (!d->ref.deref()) |
252 | delete d; |
253 | d = x; |
254 | } |
255 | |
256 | template <class T> |
257 | Q_INLINE_TEMPLATE QExplicitlySharedDataPointer<T>::QExplicitlySharedDataPointer(T *adata) : d(adata) |
258 | { if (d) d->ref.ref(); } |
259 | |
260 | template <class T> |
261 | Q_INLINE_TEMPLATE void qSwap(QSharedDataPointer<T> &p1, QSharedDataPointer<T> &p2) |
262 | { p1.swap(p2); } |
263 | |
264 | template <class T> |
265 | Q_INLINE_TEMPLATE void qSwap(QExplicitlySharedDataPointer<T> &p1, QExplicitlySharedDataPointer<T> &p2) |
266 | { p1.swap(p2); } |
267 | |
268 | #ifndef QT_NO_STL |
269 | QT_END_NAMESPACE |
270 | namespace std { |
271 | template <class T> |
272 | Q_INLINE_TEMPLATE void swap(QT_PREPEND_NAMESPACE(QSharedDataPointer)<T> &p1, QT_PREPEND_NAMESPACE(QSharedDataPointer)<T> &p2) |
273 | { p1.swap(p2); } |
274 | |
275 | template <class T> |
276 | Q_INLINE_TEMPLATE void swap(QT_PREPEND_NAMESPACE(QExplicitlySharedDataPointer)<T> &p1, QT_PREPEND_NAMESPACE(QExplicitlySharedDataPointer)<T> &p2) |
277 | { p1.swap(p2); } |
278 | } |
279 | QT_BEGIN_NAMESPACE |
280 | #endif |
281 | |
282 | QT_END_NAMESPACE |
283 | |
284 | QT_END_HEADER |
285 | |
286 | #endif // QSHAREDDATA_H |
287 | |