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