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