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