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