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, ¤tValue); }+ 102 bool testAndSetAcquire(T expectedValue, T newValue, ref T currentValue)/+ noexcept+/ 103 { return Ops.testAndSetAcquire(_q_value, expectedValue, newValue, ¤tValue); } 104 bool testAndSetRelease(T expectedValue, T newValue, ref T currentValue)/+ noexcept+/ 105 { return Ops.testAndSetRelease(_q_value, expectedValue, newValue, ¤tValue); } 106 bool testAndSetOrdered(T expectedValue, T newValue, ref T currentValue)/+ noexcept+/ 107 { return Ops.testAndSetOrdered(_q_value, expectedValue, newValue, ¤tValue); } 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 ¤tValue) noexcept 233 { return Ops::testAndSetRelaxed(_q_value, expectedValue, newValue, ¤tValue); } 234 bool testAndSetAcquire(Type expectedValue, Type newValue, Type ¤tValue) noexcept 235 { return Ops::testAndSetAcquire(_q_value, expectedValue, newValue, ¤tValue); } 236 bool testAndSetRelease(Type expectedValue, Type newValue, Type ¤tValue) noexcept 237 { return Ops::testAndSetRelease(_q_value, expectedValue, newValue, ¤tValue); } 238 bool testAndSetOrdered(Type expectedValue, Type newValue, Type ¤tValue) noexcept 239 { return Ops::testAndSetOrdered(_q_value, expectedValue, newValue, ¤tValue); } 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