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.basicatomic;
13 extern(C++):
14 
15 import core.atomic;
16 import core.stdc.config;
17 import qt.config;
18 import qt.core.typeinfo;
19 import qt.helpers;
20 
21 /+ #ifndef QBASICATOMIC_H +/
22 /+ #define QBASICATOMIC_H
23 
24 #if defined(QT_BOOTSTRAPPED)
25 // If C++11 atomics are supported, use them!
26 // Note that constexpr support is sometimes disabled in QNX or INTEGRITY builds,
27 // but their libraries have <atomic>.
28 #elif defined(Q_COMPILER_ATOMICS)
29 // No fallback
30 #else
31 #  error "Qt requires C++11 support"
32 #endif
33 
34 QT_WARNING_PUSH
35 QT_WARNING_DISABLE_MSVC(4522)
36 
37 
38 #if 0
39 // silence syncqt warnings
40 #pragma qt_no_master_include
41 #pragma qt_sync_stop_processing
42 #endif
43 
44 // New atomics
45 
46 #define QT_BASIC_ATOMIC_HAS_CONSTRUCTORS +/
47 
48 extern(C++, class) struct QBasicAtomicInteger(T)
49 {
50 public:
51     alias Type = T;
52     //alias Ops = QAtomicOps!(T);
53     // static check that this is a valid integer
54     static assert(QTypeInfo!(T).isIntegral, "template parameter is not an integral type");
55 //    static assert(QAtomicOpsSupport!(T.sizeof).IsSupported, "template parameter is an integral of a size not supported on this platform");
56 
57     Type _q_value;
58 
59     // Everything below is either implemented in ../arch/qatomic_XXX.h or (as
60     // fallback) in qgenericatomic.h
61 
62     T loadRelaxed() const/+ noexcept+/
63     {
64         return atomicLoad!(MemoryOrder.raw)(_q_value); 
65     }
66 //    void storeRelaxed(T newValue)/+ noexcept+/ { Ops.storeRelaxed(_q_value, newValue); }
67 
68     T loadAcquire() const/+ noexcept+/{ return atomicLoad!(MemoryOrder.acq)(_q_value);  }
69     void storeRelease(T newValue)/+ noexcept+/ { atomicStore!(MemoryOrder.rel)(_q_value, newValue); }
70     /+auto opCast(T : T)() const/+ noexcept+/ { return loadAcquire(); }+/
71     /+T operator =(T newValue)/+ noexcept+/ { storeRelease(newValue); return newValue; }+/
72 
73 //    static bool isReferenceCountingNative()/+ noexcept+/ { return Ops.isReferenceCountingNative(); }
74 //    static bool isReferenceCountingWaitFree()/+ noexcept+/ { return Ops.isReferenceCountingWaitFree(); }
75 
76     bool ref_()/+ noexcept+/ 
77     {
78         return atomicFetchAdd(_q_value, 1) + 1 != 0;
79     }
80     bool deref()/+ noexcept+/
81     {
82         return atomicFetchSub(_q_value, 1) - 1 != 0;
83     }
84 
85 //    static bool isTestAndSetNative()/+ noexcept+/ { return Ops.isTestAndSetNative(); }
86 //    static bool isTestAndSetWaitFree()/+ noexcept+/ { return Ops.isTestAndSetWaitFree(); }
87 
88     bool testAndSetRelaxed(T expectedValue, T newValue)/+ noexcept+/
89     {
90         bool tmp = cas!(MemoryOrder.raw, MemoryOrder.raw)(&_q_value, expectedValue, newValue);
91         return tmp;
92     }
93 /+    bool testAndSetAcquire(T expectedValue, T newValue)/+ noexcept+/
94     { return Ops.testAndSetAcquire(_q_value, expectedValue, newValue); }
95     bool testAndSetRelease(T expectedValue, T newValue)/+ noexcept+/
96     { return Ops.testAndSetRelease(_q_value, expectedValue, newValue); }
97     bool testAndSetOrdered(T expectedValue, T newValue)/+ noexcept+/
98     { return Ops.testAndSetOrdered(_q_value, expectedValue, newValue); }
99 +/
100     /+bool testAndSetRelaxed(T expectedValue, T newValue, ref T currentValue)/+ noexcept+/
101     { return Ops.testAndSetRelaxed(_q_value, expectedValue, newValue, &currentValue); }+
102     bool testAndSetAcquire(T expectedValue, T newValue, ref T currentValue)/+ noexcept+/
103     { return Ops.testAndSetAcquire(_q_value, expectedValue, newValue, &currentValue); }
104     bool testAndSetRelease(T expectedValue, T newValue, ref T currentValue)/+ noexcept+/
105     { return Ops.testAndSetRelease(_q_value, expectedValue, newValue, &currentValue); }
106     bool testAndSetOrdered(T expectedValue, T newValue, ref T currentValue)/+ noexcept+/
107     { return Ops.testAndSetOrdered(_q_value, expectedValue, newValue, &currentValue); }
108 +/
109 //    static bool isFetchAndStoreNative()/+ noexcept+/ { return Ops.isFetchAndStoreNative(); }
110 //    static bool isFetchAndStoreWaitFree()/+ noexcept+/ { return Ops.isFetchAndStoreWaitFree(); }
111 
112 /*    T fetchAndStoreRelaxed(T newValue)/+ noexcept+/
113     { return Ops.fetchAndStoreRelaxed(_q_value, newValue); }
114     T fetchAndStoreAcquire(T newValue)/+ noexcept+/
115     { return Ops.fetchAndStoreAcquire(_q_value, newValue); }
116     T fetchAndStoreRelease(T newValue)/+ noexcept+/
117     { return Ops.fetchAndStoreRelease(_q_value, newValue); }
118     T fetchAndStoreOrdered(T newValue)/+ noexcept+/
119     { return Ops.fetchAndStoreOrdered(_q_value, newValue); }*/
120 
121 //    static bool isFetchAndAddNative()/+ noexcept+/ { return Ops.isFetchAndAddNative(); }
122 //    static bool isFetchAndAddWaitFree()/+ noexcept+/ { return Ops.isFetchAndAddWaitFree(); }
123 
124 /+    T fetchAndAddRelaxed(T valueToAdd)/+ noexcept+/
125     { return Ops.fetchAndAddRelaxed(_q_value, valueToAdd); }
126     T fetchAndAddAcquire(T valueToAdd)/+ noexcept+/
127     { return Ops.fetchAndAddAcquire(_q_value, valueToAdd); }
128     T fetchAndAddRelease(T valueToAdd)/+ noexcept+/
129     { return Ops.fetchAndAddRelease(_q_value, valueToAdd); }
130     T fetchAndAddOrdered(T valueToAdd)/+ noexcept+/
131     { return Ops.fetchAndAddOrdered(_q_value, valueToAdd); }
132 
133     T fetchAndSubRelaxed(T valueToAdd)/+ noexcept+/
134     { return Ops.fetchAndSubRelaxed(_q_value, valueToAdd); }
135     T fetchAndSubAcquire(T valueToAdd)/+ noexcept+/
136     { return Ops.fetchAndSubAcquire(_q_value, valueToAdd); }
137     T fetchAndSubRelease(T valueToAdd)/+ noexcept+/
138     { return Ops.fetchAndSubRelease(_q_value, valueToAdd); }
139     T fetchAndSubOrdered(T valueToAdd)/+ noexcept+/
140     { return Ops.fetchAndSubOrdered(_q_value, valueToAdd); }
141 
142     T fetchAndAndRelaxed(T valueToAdd)/+ noexcept+/
143     { return Ops.fetchAndAndRelaxed(_q_value, valueToAdd); }
144     T fetchAndAndAcquire(T valueToAdd)/+ noexcept+/
145     { return Ops.fetchAndAndAcquire(_q_value, valueToAdd); }
146     T fetchAndAndRelease(T valueToAdd)/+ noexcept+/
147     { return Ops.fetchAndAndRelease(_q_value, valueToAdd); }
148     T fetchAndAndOrdered(T valueToAdd)/+ noexcept+/
149     { return Ops.fetchAndAndOrdered(_q_value, valueToAdd); }
150 
151     T fetchAndOrRelaxed(T valueToAdd)/+ noexcept+/
152     { return Ops.fetchAndOrRelaxed(_q_value, valueToAdd); }
153     T fetchAndOrAcquire(T valueToAdd)/+ noexcept+/
154     { return Ops.fetchAndOrAcquire(_q_value, valueToAdd); }
155     T fetchAndOrRelease(T valueToAdd)/+ noexcept+/
156     { return Ops.fetchAndOrRelease(_q_value, valueToAdd); }
157     T fetchAndOrOrdered(T valueToAdd)/+ noexcept+/
158     { return Ops.fetchAndOrOrdered(_q_value, valueToAdd); }
159 
160     T fetchAndXorRelaxed(T valueToAdd)/+ noexcept+/
161     { return Ops.fetchAndXorRelaxed(_q_value, valueToAdd); }
162     T fetchAndXorAcquire(T valueToAdd)/+ noexcept+/
163     { return Ops.fetchAndXorAcquire(_q_value, valueToAdd); }
164     T fetchAndXorRelease(T valueToAdd)/+ noexcept+/
165     { return Ops.fetchAndXorRelease(_q_value, valueToAdd); }
166     T fetchAndXorOrdered(T valueToAdd)/+ noexcept+/
167     { return Ops.fetchAndXorOrdered(_q_value, valueToAdd); }
168 +/
169     T opUnary(string op)()/+ noexcept+/ if(op == "++")
170     { return fetchAndAddOrdered(1) + 1; }
171     /+T operator ++(int)/+ noexcept+/
172     { return fetchAndAddOrdered(1); }+/
173     T opUnary(string op)()/+ noexcept+/ if(op == "--")
174     { return fetchAndSubOrdered(1) - 1; }
175     /+T operator --(int)/+ noexcept+/
176     { return fetchAndSubOrdered(1); }+/
177 
178     T opOpAssign(string op)(T v)/+ noexcept+/ if(op == "+")
179     { return fetchAndAddOrdered(v) + v; }
180     T opOpAssign(string op)(T v)/+ noexcept+/ if(op == "-")
181     { return fetchAndSubOrdered(v) - v; }
182     T opOpAssign(string op)(T v)/+ noexcept+/ if(op == "&")
183     { return fetchAndAndOrdered(v) & v; }
184     T opOpAssign(string op)(T v)/+ noexcept+/ if(op == "|")
185     { return fetchAndOrOrdered(v) | v; }
186     /+T operator ^=(T v)/+ noexcept+/
187     { return fetchAndXorOrdered(v) ^ v; }+/
188 
189 
190 /+ #ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
191     QBasicAtomicInteger() = default;
192     constexpr QBasicAtomicInteger(T value) noexcept : _q_value(value) {}
193     QBasicAtomicInteger(const QBasicAtomicInteger &) = delete;
194     QBasicAtomicInteger &operator=(const QBasicAtomicInteger &) = delete;
195     QBasicAtomicInteger &operator=(const QBasicAtomicInteger &) volatile = delete;
196 #endif +/
197 }
198 alias QBasicAtomicInt = QBasicAtomicInteger!(int);
199 
200 /+ template <typename X>
201 class QBasicAtomicPointer
202 {
203 public:
204     typedef X *Type;
205     typedef QAtomicOps<Type> Ops;
206     typedef typename Ops::Type AtomicType;
207 
208     AtomicType _q_value;
209 
210     Type loadRelaxed() const noexcept { return Ops::loadRelaxed(_q_value); }
211     void storeRelaxed(Type newValue) noexcept { Ops::storeRelaxed(_q_value, newValue); }
212 
213     operator Type() const noexcept { return loadAcquire(); }
214     Type operator=(Type newValue) noexcept { storeRelease(newValue); return newValue; }
215 
216     // Atomic API, implemented in qatomic_XXX.h
217     Type loadAcquire() const noexcept { return Ops::loadAcquire(_q_value); }
218     void storeRelease(Type newValue) noexcept { Ops::storeRelease(_q_value, newValue); }
219 
220     static constexpr bool isTestAndSetNative() noexcept { return Ops::isTestAndSetNative(); }
221     static constexpr bool isTestAndSetWaitFree() noexcept { return Ops::isTestAndSetWaitFree(); }
222 
223     bool testAndSetRelaxed(Type expectedValue, Type newValue) noexcept
224     { return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue); }
225     bool testAndSetAcquire(Type expectedValue, Type newValue) noexcept
226     { return Ops::testAndSetAcquire(_q_value, expectedValue, newValue); }
227     bool testAndSetRelease(Type expectedValue, Type newValue) noexcept
228     { return Ops::testAndSetRelease(_q_value, expectedValue, newValue); }
229     bool testAndSetOrdered(Type expectedValue, Type newValue) noexcept
230     { return Ops::testAndSetOrdered(_q_value, expectedValue, newValue); }
231 
232     bool testAndSetRelaxed(Type expectedValue, Type newValue, Type &currentValue) noexcept
233     { return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue, &currentValue); }
234     bool testAndSetAcquire(Type expectedValue, Type newValue, Type &currentValue) noexcept
235     { return Ops::testAndSetAcquire(_q_value, expectedValue, newValue, &currentValue); }
236     bool testAndSetRelease(Type expectedValue, Type newValue, Type &currentValue) noexcept
237     { return Ops::testAndSetRelease(_q_value, expectedValue, newValue, &currentValue); }
238     bool testAndSetOrdered(Type expectedValue, Type newValue, Type &currentValue) noexcept
239     { return Ops::testAndSetOrdered(_q_value, expectedValue, newValue, &currentValue); }
240 
241     static constexpr bool isFetchAndStoreNative() noexcept { return Ops::isFetchAndStoreNative(); }
242     static constexpr bool isFetchAndStoreWaitFree() noexcept { return Ops::isFetchAndStoreWaitFree(); }
243 
244     Type fetchAndStoreRelaxed(Type newValue) noexcept
245     { return Ops::fetchAndStoreRelaxed(_q_value, newValue); }
246     Type fetchAndStoreAcquire(Type newValue) noexcept
247     { return Ops::fetchAndStoreAcquire(_q_value, newValue); }
248     Type fetchAndStoreRelease(Type newValue) noexcept
249     { return Ops::fetchAndStoreRelease(_q_value, newValue); }
250     Type fetchAndStoreOrdered(Type newValue) noexcept
251     { return Ops::fetchAndStoreOrdered(_q_value, newValue); }
252 
253     static constexpr bool isFetchAndAddNative() noexcept { return Ops::isFetchAndAddNative(); }
254     static constexpr bool isFetchAndAddWaitFree() noexcept { return Ops::isFetchAndAddWaitFree(); }
255 
256     Type fetchAndAddRelaxed(qptrdiff valueToAdd) noexcept
257     { return Ops::fetchAndAddRelaxed(_q_value, valueToAdd); }
258     Type fetchAndAddAcquire(qptrdiff valueToAdd) noexcept
259     { return Ops::fetchAndAddAcquire(_q_value, valueToAdd); }
260     Type fetchAndAddRelease(qptrdiff valueToAdd) noexcept
261     { return Ops::fetchAndAddRelease(_q_value, valueToAdd); }
262     Type fetchAndAddOrdered(qptrdiff valueToAdd) noexcept
263     { return Ops::fetchAndAddOrdered(_q_value, valueToAdd); }
264 
265     Type fetchAndSubRelaxed(qptrdiff valueToAdd) noexcept
266     { return Ops::fetchAndSubRelaxed(_q_value, valueToAdd); }
267     Type fetchAndSubAcquire(qptrdiff valueToAdd) noexcept
268     { return Ops::fetchAndSubAcquire(_q_value, valueToAdd); }
269     Type fetchAndSubRelease(qptrdiff valueToAdd) noexcept
270     { return Ops::fetchAndSubRelease(_q_value, valueToAdd); }
271     Type fetchAndSubOrdered(qptrdiff valueToAdd) noexcept
272     { return Ops::fetchAndSubOrdered(_q_value, valueToAdd); }
273 
274     Type operator++() noexcept
275     { return fetchAndAddOrdered(1) + 1; }
276     Type operator++(int) noexcept
277     { return fetchAndAddOrdered(1); }
278     Type operator--() noexcept
279     { return fetchAndSubOrdered(1) - 1; }
280     Type operator--(int) noexcept
281     { return fetchAndSubOrdered(1); }
282     Type operator+=(qptrdiff valueToAdd) noexcept
283     { return fetchAndAddOrdered(valueToAdd) + valueToAdd; }
284     Type operator-=(qptrdiff valueToSub) noexcept
285     { return fetchAndSubOrdered(valueToSub) - valueToSub; }
286 
287 #ifdef QT_BASIC_ATOMIC_HAS_CONSTRUCTORS
288     QBasicAtomicPointer() = default;
289     constexpr QBasicAtomicPointer(Type value) noexcept : _q_value(value) {}
290     QBasicAtomicPointer(const QBasicAtomicPointer &) = delete;
291     QBasicAtomicPointer &operator=(const QBasicAtomicPointer &) = delete;
292     QBasicAtomicPointer &operator=(const QBasicAtomicPointer &) volatile = delete;
293 #endif
294 };
295 
296 #ifndef Q_BASIC_ATOMIC_INITIALIZER
297 #  define Q_BASIC_ATOMIC_INITIALIZER(a) { (a) }
298 #endif
299 
300 
301 QT_WARNING_POP +/
302 
303 /+ #endif +/ // QBASICATOMIC_H
304