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.atomic;
13 extern(C++):
14 
15 import qt.config;
16 import qt.core.basicatomic;
17 import qt.helpers;
18 
19 /+ #ifndef QATOMIC_H +/
20 /+ #define QATOMIC_H
21 
22 
23 QT_WARNING_PUSH
24 QT_WARNING_DISABLE_GCC("-Wextra")
25 
26 #ifdef Q_CLANG_QDOC
27 #  undef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
28 #endif +/
29 
30 // High-level atomic integer operations
31 /// Binding for C++ class [QAtomicInteger](https://doc.qt.io/qt-6/qatomicinteger.html).
32 extern(C++, class) struct QAtomicInteger(T)
33 {
34     public QBasicAtomicInteger!(T) base0;
35     alias base0 this;
36 public:
37     // Non-atomic API
38 /+ #ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
39     constexpr QAtomicInteger(T value = 0) noexcept : QBasicAtomicInteger<T>(value) {}
40 #else +/
41     @disable this();
42     pragma(inline, true) this(T value/+ = 0+/)/+ noexcept+/
43     {
44         this._q_value = value;
45     }
46 /+ #endif +/
47 
48     @disable this(this);
49     pragma(inline, true) this(ref const(QAtomicInteger) other)/+ noexcept+/
50 /+ #ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
51         : QBasicAtomicInteger<T>()
52 #endif +/
53     {
54         base0.storeRelease(other.base0.loadAcquire());
55     }
56 
57     /+pragma(inline, true) ref QAtomicInteger operator =(ref const(QAtomicInteger) other)/+ noexcept+/
58     {
59         this.storeRelease(other.loadAcquire());
60         return this;
61     }+/
62 
63 /+ #ifdef Q_CLANG_QDOC
64     T loadRelaxed() const;
65     T loadAcquire() const;
66     void storeRelaxed(T newValue);
67     void storeRelease(T newValue);
68 
69     operator T() const;
70     QAtomicInteger &operator=(T);
71 
72     static constexpr bool isReferenceCountingNative();
73     static constexpr bool isReferenceCountingWaitFree();
74 
75     bool ref();
76     bool deref();
77 
78     static constexpr bool isTestAndSetNative();
79     static constexpr bool isTestAndSetWaitFree();
80 
81     bool testAndSetRelaxed(T expectedValue, T newValue);
82     bool testAndSetAcquire(T expectedValue, T newValue);
83     bool testAndSetRelease(T expectedValue, T newValue);
84     bool testAndSetOrdered(T expectedValue, T newValue);
85 
86     static constexpr bool isFetchAndStoreNative();
87     static constexpr bool isFetchAndStoreWaitFree();
88 
89     T fetchAndStoreRelaxed(T newValue);
90     T fetchAndStoreAcquire(T newValue);
91     T fetchAndStoreRelease(T newValue);
92     T fetchAndStoreOrdered(T newValue);
93 
94     static constexpr bool isFetchAndAddNative();
95     static constexpr bool isFetchAndAddWaitFree();
96 
97     T fetchAndAddRelaxed(T valueToAdd);
98     T fetchAndAddAcquire(T valueToAdd);
99     T fetchAndAddRelease(T valueToAdd);
100     T fetchAndAddOrdered(T valueToAdd);
101 
102     T fetchAndSubRelaxed(T valueToSub);
103     T fetchAndSubAcquire(T valueToSub);
104     T fetchAndSubRelease(T valueToSub);
105     T fetchAndSubOrdered(T valueToSub);
106 
107     T fetchAndOrRelaxed(T valueToOr);
108     T fetchAndOrAcquire(T valueToOr);
109     T fetchAndOrRelease(T valueToOr);
110     T fetchAndOrOrdered(T valueToOr);
111 
112     T fetchAndAndRelaxed(T valueToAnd);
113     T fetchAndAndAcquire(T valueToAnd);
114     T fetchAndAndRelease(T valueToAnd);
115     T fetchAndAndOrdered(T valueToAnd);
116 
117     T fetchAndXorRelaxed(T valueToXor);
118     T fetchAndXorAcquire(T valueToXor);
119     T fetchAndXorRelease(T valueToXor);
120     T fetchAndXorOrdered(T valueToXor);
121 
122     T operator++();
123     T operator++(int);
124     T operator--();
125     T operator--(int);
126     T operator+=(T value);
127     T operator-=(T value);
128     T operator|=(T value);
129     T operator&=(T value);
130     T operator^=(T value);
131 #endif +/
132 }
133 
134 /// Binding for C++ class [QAtomicInt](https://doc.qt.io/qt-6/qatomicint.html).
135 extern(C++, class) struct QAtomicInt
136 {
137     public QAtomicInteger!(int) base0;
138     alias base0 this;
139 public:
140     // Non-atomic API
141     // We could use QT_COMPILER_INHERITING_CONSTRUCTORS, but we need only one;
142     // the implicit definition for all the others is fine.
143 /+ #ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
144     constexpr
145 #endif +/
146     @disable this();
147     this(int value/+ = 0+/)/+ noexcept+/
148     {
149         this.base0 = typeof(this.base0)(value);
150     }
151     mixin(CREATE_CONVENIENCE_WRAPPERS);
152 }
153 
154 // High-level atomic pointer operations
155 /// Binding for C++ class [QAtomicPointer](https://doc.qt.io/qt-6/qatomicpointer.html).
156 extern(C++, class) struct QAtomicPointer(T)
157 {
158     public QBasicAtomicPointer!(T) base0;
159     alias base0 this;
160 public:
161 /+ #ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
162     constexpr QAtomicPointer(T *value = nullptr) noexcept : QBasicAtomicPointer<T>(value) {}
163 #else +/
164     @disable this();
165     pragma(inline, true) this(T* value/+ = null+/)/+ noexcept+/
166     {
167         this.storeRelaxed(value);
168     }
169 /+ #endif +/
170     @disable this(this);
171     pragma(inline, true) this(ref const(QAtomicPointer!(T)) other)/+ noexcept+/
172 /+ #ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
173         : QBasicAtomicPointer<T>()
174 #endif +/
175     {
176         this.storeRelease(other.loadAcquire());
177     }
178 
179     /+pragma(inline, true) ref QAtomicPointer!(T) operator =(ref const(QAtomicPointer!(T)) other)/+ noexcept+/
180     {
181         this.storeRelease(other.loadAcquire());
182         return this;
183     }+/
184 
185 /+ #ifdef Q_QDOC
186     T *loadAcquire() const;
187     T *loadRelaxed() const;
188     void storeRelaxed(T *newValue);
189     void storeRelease(T *newValue);
190 
191     static constexpr bool isTestAndSetNative();
192     static constexpr bool isTestAndSetWaitFree();
193 
194     bool testAndSetRelaxed(T *expectedValue, T *newValue);
195     bool testAndSetAcquire(T *expectedValue, T *newValue);
196     bool testAndSetRelease(T *expectedValue, T *newValue);
197     bool testAndSetOrdered(T *expectedValue, T *newValue);
198 
199     static constexpr bool isFetchAndStoreNative();
200     static constexpr bool isFetchAndStoreWaitFree();
201 
202     T *fetchAndStoreRelaxed(T *newValue);
203     T *fetchAndStoreAcquire(T *newValue);
204     T *fetchAndStoreRelease(T *newValue);
205     T *fetchAndStoreOrdered(T *newValue);
206 
207     static constexpr bool isFetchAndAddNative();
208     static constexpr bool isFetchAndAddWaitFree();
209 
210     T *fetchAndAddRelaxed(qptrdiff valueToAdd);
211     T *fetchAndAddAcquire(qptrdiff valueToAdd);
212     T *fetchAndAddRelease(qptrdiff valueToAdd);
213     T *fetchAndAddOrdered(qptrdiff valueToAdd);
214 #endif +/
215 }
216 
217 /+ QT_WARNING_POP
218 
219 #ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
220 #  undef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
221 #endif +/
222 
223 /*!
224     This is a helper for the assignment operators of implicitly
225     shared classes. Your assignment operator should look like this:
226 
227     \snippet code/src.corelib.thread.qatomic.h 0
228 */
229 pragma(inline, true) void qAtomicAssign(T)(ref T* d, T* x)
230 {
231     import core.stdcpp.new_;
232 
233     if (d == x)
234         return;
235     x.ref_.ref_();
236     if (!d.ref_.deref())
237         cpp_delete(d);
238     d = x;
239 }
240 
241 /*!
242     This is a helper for the detach method of implicitly shared
243     classes. Your private class needs a copy constructor which copies
244     the members and sets the refcount to 1. After that, your detach
245     function should look like this:
246 
247     \snippet code/src.corelib.thread.qatomic.h 1
248 */
249 pragma(inline, true) void qAtomicDetach(T)(ref T* d)
250 {
251     import core.stdcpp.new_;
252 
253     if (d.ref_.loadRelaxed() == 1)
254         return;
255     T* x = d;
256     d = cpp_new!T(*d);
257     if (!x.ref_.deref())
258         cpp_delete(x);
259 }
260 
261 /+ #endif +/ // QATOMIC_H
262