1 /** 2 Atomic Data Wrappers 3 4 Copyright: 5 Copyright © 2023-2025, Kitsunebi Games 6 Copyright © 2023-2025, Inochi2D Project 7 8 License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 9 Authors: Luna Nielsen 10 */ 11 module nulib.threading.atomic; 12 import numem; 13 14 /** 15 Atomic pointer sized unsigned integer.. 16 */ 17 alias asize_t = Atomic!size_t; 18 19 /** 20 Atomic pointer sized signed integer.. 21 */ 22 alias aptrdiff_t = Atomic!ptrdiff_t; 23 24 /** 25 Atomic 32 bit floating point number. 26 */ 27 alias afloat = Atomic!float; 28 29 /** 30 Atomic 32 bit unsigned integer. 31 */ 32 alias auint = Atomic!uint; 33 34 /** 35 Atomic 32 bit signed integer. 36 */ 37 alias aint = Atomic!int; 38 39 /** 40 Atomic 16 bit unsigned integer. 41 */ 42 alias aushort = Atomic!ushort; 43 44 /** 45 Atomic 16 bit signed integer. 46 */ 47 alias ashort = Atomic!short; 48 49 /** 50 Atomic 8 bit unsigned integer. 51 */ 52 alias aubyte = Atomic!ubyte; 53 54 /** 55 Atomic 8 bit signed integer. 56 */ 57 alias abyte = Atomic!byte; 58 59 /** 60 Wraps a type for atomic reading and writing. 61 */ 62 struct Atomic(T) if (T.sizeof <= (void*).sizeof) { 63 private: 64 @nogc: 65 AtomicT value_; 66 67 union AtomicT { 68 T ut; 69 void* ptr; 70 } 71 72 public: 73 alias value this; 74 75 /** 76 The value of the atomic type. 77 */ 78 @property T value() { 79 auto v = nu_atomic_load_ptr(cast(void**)&value_); 80 return *cast(T*)&v; 81 } 82 @property void value(T value) { 83 auto v = AtomicT(value); 84 nu_atomic_store_ptr(cast(void**)&value_, v.ptr); 85 } 86 87 /** 88 Constructs a new atomic value. 89 */ 90 this(T value) { 91 auto v = AtomicT(value); 92 nu_atomic_store_ptr(cast(void**)&value_, v.ptr); 93 } 94 95 /** 96 Atomic assignment 97 */ 98 auto ref opAssign(Y)(inout(Y) value) if (is(T : Y)) { 99 this.value = cast(T)value; 100 return this; 101 } 102 103 /** 104 Allows performing arithmetic operations on the given values. 105 */ 106 auto ref opOpAssign(string op, Y)(inout(Y) value) if (__traits(isScalar, T) && is(T : Y)) { 107 AtomicT oldv; 108 AtomicT tmpv; 109 oldv.ptr = nu_atomic_load_ptr(&value_.ptr); 110 tmpv.ut = cast(T)value; 111 112 mixin("tmpv.ut = oldv.ut ", op, " tmpv.ut;"); 113 nu_atomic_cmpxhg_ptr(&value_.ptr, oldv.ptr, tmpv.ptr); 114 return this; 115 } 116 } 117 118 @("atomic operations") 119 unittest { 120 afloat f = 32.0; 121 f += 10.0; 122 assert(f == 42.0); 123 124 f = 10.0; 125 assert(f == 10.0); 126 }