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 }