1 /****************************************************************************
2 **
3 ** DQt - D bindings for the Qt Toolkit
4 **
5 ** GNU Lesser General Public License Usage
6 ** This file may be used under the terms of the GNU Lesser
7 ** General Public License version 3 as published by the Free Software
8 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 ** packaging of this file. Please review the following information to
10 ** ensure the GNU Lesser General Public License version 3 requirements
11 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 **
13 ****************************************************************************/
14 module qt.core.shareddata;
15 extern(C++):
16 
17 import qt.config;
18 import qt.core.atomic;
19 import qt.helpers;
20 
21 /+ #if QT_DEPRECATED_SINCE(5, 6)
22 #endif
23 
24 
25 template <class T> class QSharedDataPointer; +/
26 
27 extern(C++, class) struct
28 /+ #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
29 Q_CORE_EXPORT
30 #endif +/
31 QSharedData
32 {
33 public:
34     /+ mutable +/ QAtomicInt ref_/* = 0*/;
35 
36     @disable this();
37     /+pragma(inline, true) this()/+ noexcept+/
38     {
39         this.ref_ = 0;
40     }+/
41     @disable this(this);
42     pragma(inline, true) this(ref const(QSharedData) )/+ noexcept+/
43     {
44         this.ref_ = 0;
45     }
46 
47     // using the assignment operator would lead to corruption in the ref-counting
48     /+ref QSharedData operator =(ref const(QSharedData) ) /+ = delete +/;+/
49     /+ ~QSharedData() = default; +/
50 }
51 
52 extern(C++, class) struct QSharedDataPointer(T)
53 {
54 public:
55     alias Type = T;
56     alias pointer = T*;
57 
58     pragma(inline, true) void detach()() { if (d && d.ref_.loadRelaxed() != 1) detach_helper(); }
59     pragma(inline, true) ref T opUnary(string op)() if(op == "*") { detach(); return *d; }
60     pragma(inline, true) ref const(T) opUnary(string op)() const if(op == "*") { return *d; }
61     /+pragma(inline, true) T* operator ->() { detach(); return d; }+/
62     /+pragma(inline, true) const(T)* operator ->() const { return d; }+/
63     /+pragma(inline, true) auto opCast(T : T)() { detach(); return d; }+/
64     /+pragma(inline, true) auto opCast(T : const(T))() const { return d; }+/
65     pragma(inline, true) T* data()() { detach(); return d; }
66     pragma(inline, true) const(T)* data()() const { return d; }
67     pragma(inline, true) const(T)* constData() const { return d; }
68 
69     /+pragma(inline, true) bool operator ==(ref const(QSharedDataPointer!(T)) other) const { return d == other.d; }+/
70     /+pragma(inline, true) bool operator !=(ref const(QSharedDataPointer!(T)) other) const { return d != other.d; }+/
71 
72     /+pragma(inline, true) this() { d = null; }+/
73     pragma(inline, true) ~this() {
74         import core.stdcpp.new_;
75         static if(__traits(compiles, (*d).sizeof))
76         {
77             import core.stdcpp.new_;
78             if (d && !d.ref_.deref()) cpp_delete(d);
79         }
80         else
81             assert(false);
82     }
83 
84 /+    /+ explicit +/pragma(inline, true) this(T* adata)/+ noexcept+/
85     {
86         this.d = adata;
87         if (d) d.ref_.ref_();
88     }+/
89     @disable this(this);
90     pragma(inline, true) this(ref const(QSharedDataPointer!(T)) o)
91     {
92         this.d = cast(T*)o.d;
93         static if(__traits(compiles, d.ref_))
94         {
95             if (d) d.ref_.ref_();
96         }
97         else
98             assert(0);
99     }
100     /+pragma(inline, true) ref QSharedDataPointer!(T)  operator =(ref const(QSharedDataPointer!(T)) o) {
101         import core.stdcpp.new_;
102 
103         if (o.d != d) {
104             if (o.d)
105                 o.d.ref_.ref_();
106             T* old = d;
107             d = o.d;
108             if (old && !old.ref_.deref())
109                 cpp_delete(old);
110         }
111         return this;
112     }+/
113     /+pragma(inline, true) ref QSharedDataPointer operator =(T* o) {
114         import core.stdcpp.new_;
115 
116         if (o != d) {
117             if (o)
118                 o.ref_.ref_();
119             T* old = d;
120             d = o;
121             if (old && !old.ref_.deref())
122                 cpp_delete(old);
123         }
124         return this;
125     }+/
126     /+ QSharedDataPointer(QSharedDataPointer &&o) noexcept : d(o.d) { o.d = nullptr; } +/
127     /+ inline QSharedDataPointer<T> &operator=(QSharedDataPointer<T> &&other) noexcept
128     {
129         QSharedDataPointer moved(std::move(other));
130         swap(moved);
131         return *this;
132     } +/
133 
134     /+pragma(inline, true) bool operator !() const { return !d; }+/
135 
136     /+ inline void swap(QSharedDataPointer &other) noexcept
137     { qSwap(d, other.d); } +/
138 
139 protected:
140     pragma(inline, true) T* clone()()
141     {
142         import core.stdcpp.new_;
143 
144         return cpp_new!T(*d);
145     }
146 
147 private:
148     void detach_helper()()
149     {
150         import core.stdcpp.new_;
151 
152         T* x = clone();
153         x.ref_.ref_();
154         if (!d.ref_.deref())
155             cpp_delete(d);
156         d = x;
157     }
158 
159     T* d;
160 }
161 
162 /+pragma(inline, true) bool operator ==(T)(/+ std:: +/nullptr_t p1, ref const(QSharedDataPointer!(T)) p2)
163 {
164     /+ Q_UNUSED(p1) +/
165     return !p2;
166 }+/
167 
168 /+pragma(inline, true) bool operator ==(T)(ref const(QSharedDataPointer!(T)) p1, /+ std:: +/nullptr_t p2)
169 {
170     /+ Q_UNUSED(p2) +/
171     return !p1;
172 }+/
173 
174 extern(C++, class) struct QExplicitlySharedDataPointer(T)
175 {
176 public:
177     alias Type = T;
178     alias pointer = T*;
179 
180     pragma(inline, true) ref T opUnary(string op)() const if(op == "*") { return *d; }
181     /+pragma(inline, true) T* operator ->() { return d; }+/
182     /+pragma(inline, true) T* operator ->() const { return d; }+/
183     pragma(inline, true) T* data() const { return cast(T*)d; }
184     pragma(inline, true) const(T)* constData() const { return d; }
185     pragma(inline, true) T* take() { T* x = d; d = null; return x; }
186 
187     pragma(inline, true) void detach()() { if (d && d.ref_.loadRelaxed() != 1) detach_helper(); }
188 
189     pragma(inline, true) void reset()()
190     {
191         import core.stdcpp.new_;
192 
193         if(d && !d.ref_.deref())
194             cpp_delete(d);
195 
196         d = null;
197     }
198 
199     /+pragma(inline, true) auto opCast(T : bool) () const { return d !is null; }+/
200 
201     /+pragma(inline, true) bool operator ==(ref const(QExplicitlySharedDataPointer!(T)) other) const { return d == other.d; }+/
202     /+pragma(inline, true) bool operator !=(ref const(QExplicitlySharedDataPointer!(T)) other) const { return d != other.d; }+/
203     /+pragma(inline, true) bool operator ==(const(T)* ptr) const { return d == ptr; }+/
204     /+pragma(inline, true) bool operator !=(const(T)* ptr) const { return d != ptr; }+/
205 
206     /+pragma(inline, true) this() { d = null; }+/
207     pragma(inline, true) ~this() {
208         static if(__traits(compiles, (*d).sizeof))
209         {
210             import core.stdcpp.new_;
211             if (d && !d.ref_.deref()) cpp_delete(d);
212         }
213         else
214             assert(false);
215     }
216 
217 /+    /+ explicit +/pragma(inline, true) this(T* adata)/+ noexcept+/
218     {
219         this.d = adata;
220         if (d) d.ref_.ref_();
221     }+/
222     @disable this(this);
223     pragma(inline, true) this(ref const(QExplicitlySharedDataPointer!(T)) o)
224     {
225         static if(__traits(compiles, (*d).sizeof))
226         {
227             this.d = cast(T*)o.d;
228             if (d) d.ref_.ref_();
229         }
230         else
231             assert(false);
232     }
233 
234     /+ template<class X> +/
235     /+ inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X> &o)
236 #ifdef QT_ENABLE_QEXPLICITLYSHAREDDATAPOINTER_STATICCAST
237         : d(static_cast<T *>(o.data()))
238 #else
239         : d(o.data())
240 #endif
241     {
242         if(d)
243             d->ref.ref();
244     } +/
245 
246     /+pragma(inline, true) ref QExplicitlySharedDataPointer!(T)  operator =(ref const(QExplicitlySharedDataPointer!(T)) o) {
247         import core.stdcpp.new_;
248 
249         if (o.d != d) {
250             if (o.d)
251                 o.d.ref_.ref_();
252             T* old = d;
253             d = o.d;
254             if (old && !old.ref_.deref())
255                 cpp_delete(old);
256         }
257         return this;
258     }+/
259     /+pragma(inline, true) ref QExplicitlySharedDataPointer operator =(T* o) {
260         import core.stdcpp.new_;
261 
262         if (o != d) {
263             if (o)
264                 o.ref_.ref_();
265             T* old = d;
266             d = o;
267             if (old && !old.ref_.deref())
268                 cpp_delete(old);
269         }
270         return this;
271     }+/
272     /+ inline QExplicitlySharedDataPointer(QExplicitlySharedDataPointer &&o) noexcept : d(o.d) { o.d = nullptr; } +/
273     /+ inline QExplicitlySharedDataPointer<T> &operator=(QExplicitlySharedDataPointer<T> &&other) noexcept
274     {
275         QExplicitlySharedDataPointer moved(std::move(other));
276         swap(moved);
277         return *this;
278     } +/
279 
280     /+pragma(inline, true) bool operator !() const { return !d; }+/
281 
282     /+ inline void swap(QExplicitlySharedDataPointer &other) noexcept
283     { qSwap(d, other.d); } +/
284 
285 protected:
286     pragma(inline, true) T* clone()()
287     {
288         import core.stdcpp.new_;
289 
290         return cpp_new!T(*d);
291     }
292 
293 private:
294     void detach_helper()()
295     {
296         import core.stdcpp.new_;
297 
298         T* x = clone();
299         x.ref_.ref_();
300         if (!d.ref_.deref())
301             cpp_delete(d);
302         d = x;
303     }
304 
305     T* d;
306 }
307 
308 /+pragma(inline, true) bool operator ==(T)(/+ std:: +/nullptr_t p1, ref const(QExplicitlySharedDataPointer!(T)) p2)
309 {
310     /+ Q_UNUSED(p1) +/
311     return !p2;
312 }+/
313 
314 /+pragma(inline, true) bool operator ==(T)(ref const(QExplicitlySharedDataPointer!(T)) p1, /+ std:: +/nullptr_t p2)
315 {
316     /+ Q_UNUSED(p2) +/
317     return !p1;
318 }+/
319 
320 /+ template <class T>
321 void swap(QSharedDataPointer<T> &p1, QSharedDataPointer<T> &p2)
322 { p1.swap(p2); }
323 
324 template <class T>
325 void swap(QExplicitlySharedDataPointer<T> &p1, QExplicitlySharedDataPointer<T> &p2)
326 { p1.swap(p2); }
327 
328 template <class T>
329 uint qHash(const QSharedDataPointer<T> &ptr, uint seed = 0) noexcept
330 {
331     return qHash(ptr.data(), seed);
332 }
333 template <class T>
334 uint qHash(const QExplicitlySharedDataPointer<T> &ptr, uint seed = 0) noexcept
335 {
336     return qHash(ptr.data(), seed);
337 }
338 
339 template<typename T> Q_DECLARE_TYPEINFO_BODY(QSharedDataPointer<T>, Q_MOVABLE_TYPE);
340 template<typename T> Q_DECLARE_TYPEINFO_BODY(QExplicitlySharedDataPointer<T>, Q_MOVABLE_TYPE); +/
341