@@ -69,8 +69,6 @@ pub struct AtomicVal[T] {
69
69
// new_atomic creates a new atomic value of `T` type
70
70
@[inline]
71
71
pub fn new_atomic [T](val T) & AtomicVal[T] {
72
- // can't use `$if T is $int || T is bool` with $compile_error() now
73
- // see issue #24562
74
72
$if T is $int {
75
73
return & AtomicVal[T]{
76
74
val: val
@@ -79,8 +77,12 @@ pub fn new_atomic[T](val T) &AtomicVal[T] {
79
77
return & AtomicVal[T]{
80
78
val: val
81
79
}
80
+ } $else $if T is voidptr {
81
+ return & AtomicVal[T]{
82
+ val: val
83
+ }
82
84
} $else {
83
- $compile_error ('atomic: only support number and bool types' )
85
+ $compile_error ('atomic: only support number, bool, and voidptr types' )
84
86
}
85
87
return unsafe { nil }
86
88
}
@@ -99,19 +101,24 @@ pub fn (mut a AtomicVal[T]) load() T {
99
101
} $else $if T is u64 || T is i64 {
100
102
return T (C.atomic_load_u64 (voidptr (& a.val)))
101
103
} $else $if T is int {
102
- // TODO: remove this test or a compile time support $if sizeof() ==
103
104
if sizeof (int ) == 4 {
104
105
return int (C.atomic_load_u32 (voidptr (& a.val)))
105
106
} else {
106
107
return int (C.atomic_load_u64 (voidptr (& a.val)))
107
108
}
108
109
} $else $if T is isize || T is usize {
109
- // TODO: remove this test or a compile time support $if sizeof() ==
110
110
if sizeof (isize) == 4 {
111
111
return T (C.atomic_load_u32 (voidptr (& a.val)))
112
112
} else {
113
113
return T (C.atomic_load_u64 (voidptr (& a.val)))
114
114
}
115
+ } $else $if T is voidptr {
116
+ // TODO: this should be $if sizeof(T) == 4
117
+ $if x32 {
118
+ return T (C.atomic_load_u32 (voidptr (& a.val)))
119
+ } $else {
120
+ return T (C.atomic_load_u64 (voidptr (& a.val)))
121
+ }
115
122
}
116
123
return a.val
117
124
}
@@ -120,90 +127,207 @@ pub fn (mut a AtomicVal[T]) load() T {
120
127
@[inline]
121
128
pub fn (mut a AtomicVal[T]) store (val T) {
122
129
$if T is bool {
123
- C.atomic_store_byte (voidptr (& a.val), val)
130
+ C.atomic_store_byte (voidptr (& a.val), u8 ( val) )
124
131
} $else $if T is u8 || T is i8 {
125
- C.atomic_store_byte (voidptr (& a.val), val)
132
+ C.atomic_store_byte (voidptr (& a.val), u8 ( val) )
126
133
} $else $if T is u16 || T is i16 {
127
- C.atomic_store_u16 (voidptr (& a.val), val)
134
+ C.atomic_store_u16 (voidptr (& a.val), u16 ( val) )
128
135
} $else $if T is u32 || T is i32 {
129
- C.atomic_store_u32 (voidptr (& a.val), val)
136
+ C.atomic_store_u32 (voidptr (& a.val), u32 ( val) )
130
137
} $else $if T is u64 || T is i64 {
131
- C.atomic_store_u64 (voidptr (& a.val), val)
138
+ C.atomic_store_u64 (voidptr (& a.val), u64 ( val) )
132
139
} $else $if T is int {
133
- // TODO: remove this test or a compile time support $if sizeof() ==
134
140
if sizeof (int ) == 4 {
135
- C.atomic_store_u32 (voidptr (& a.val), val)
141
+ C.atomic_store_u32 (voidptr (& a.val), u32 ( val) )
136
142
} else {
137
- C.atomic_store_u64 (voidptr (& a.val), val)
143
+ C.atomic_store_u64 (voidptr (& a.val), u64 ( val) )
138
144
}
139
145
} $else $if T is isize || T is usize {
140
- // TODO: remove this test or a compile time support $if sizeof() ==
141
146
if sizeof (isize) == 4 {
142
- C.atomic_store_u32 (voidptr (& a.val), val)
147
+ C.atomic_store_u32 (voidptr (& a.val), u32 ( val) )
143
148
} else {
144
- C.atomic_store_u64 (voidptr (& a.val), val)
149
+ C.atomic_store_u64 (voidptr (& a.val), u64 (val))
150
+ }
151
+ } $else $if T is voidptr {
152
+ // TODO: this should be $if sizeof(T) == 4
153
+ $if x32 {
154
+ C.atomic_store_u32 (voidptr (& a.val), u32 (val))
155
+ } $else {
156
+ C.atomic_store_u64 (voidptr (& a.val), u64 (val))
145
157
}
146
158
}
147
159
}
148
160
149
- // add adds the atomic value with `delta`
161
+ // add adds the atomic value with `delta` and returns the previous value
150
162
@[inline]
151
163
pub fn (mut a AtomicVal[T]) add (delta T) T {
152
164
$if T is bool {
153
- panic ('atomic: can not add() a bool type' )
165
+ panic ('atomic: add() not supported for bool type' )
166
+ } $else $if T is voidptr {
167
+ panic ('atomic: add() not supported for voidptr type' )
154
168
} $else $if T is u8 || T is i8 {
155
- C.atomic_fetch_add_byte (voidptr (& a.val), delta)
169
+ old := C.atomic_fetch_add_byte (voidptr (& a.val), u8 (delta))
170
+ return T (old)
156
171
} $else $if T is u16 || T is i16 {
157
- C.atomic_fetch_add_u16 (voidptr (& a.val), delta)
172
+ old := C.atomic_fetch_add_u16 (voidptr (& a.val), u16 (delta))
173
+ return T (old)
158
174
} $else $if T is u32 || T is i32 {
159
- C.atomic_fetch_add_u32 (voidptr (& a.val), delta)
175
+ old := C.atomic_fetch_add_u32 (voidptr (& a.val), u32 (delta))
176
+ return T (old)
160
177
} $else $if T is u64 || T is i64 {
161
- C.atomic_fetch_add_u64 (voidptr (& a.val), delta)
178
+ old := C.atomic_fetch_add_u64 (voidptr (& a.val), u64 (delta))
179
+ return T (old)
162
180
} $else $if T is int {
163
- // TODO: remove this test or a compile time support $if sizeof() ==
164
181
if sizeof (int ) == 4 {
165
- C.atomic_fetch_add_u32 (voidptr (& a.val), delta)
182
+ old := C.atomic_fetch_add_u32 (voidptr (& a.val), u32 (delta))
183
+ return T (old)
166
184
} else {
167
- C.atomic_fetch_add_u64 (voidptr (& a.val), delta)
185
+ old := C.atomic_fetch_add_u64 (voidptr (& a.val), u64 (delta))
186
+ return T (old)
168
187
}
169
188
} $else $if T is isize || T is usize {
170
- // TODO: remove this test or a compile time support $if sizeof() ==
171
189
if sizeof (isize) == 4 {
172
- C.atomic_fetch_add_u32 (voidptr (& a.val), delta)
190
+ old := C.atomic_fetch_add_u32 (voidptr (& a.val), u32 (delta))
191
+ return T (old)
173
192
} else {
174
- C.atomic_fetch_add_u64 (voidptr (& a.val), delta)
193
+ old := C.atomic_fetch_add_u64 (voidptr (& a.val), u64 (delta))
194
+ return T (old)
175
195
}
176
196
}
177
- return T (a.val )
197
+ panic ( 'unreachable' )
178
198
}
179
199
180
- // sub subs the atomic value with `delta`
200
+ // sub subtracts the atomic value with `delta` and returns the previous value
181
201
@[inline]
182
202
pub fn (mut a AtomicVal[T]) sub (delta T) T {
183
203
$if T is bool {
184
- panic ('atomic: can not sub() a bool type' )
204
+ panic ('atomic: sub() not supported for bool type' )
205
+ } $else $if T is voidptr {
206
+ panic ('atomic: sub() not supported for voidptr type' )
185
207
} $else $if T is u8 || T is i8 {
186
- C.atomic_fetch_sub_byte (voidptr (& a.val), delta)
208
+ old := C.atomic_fetch_sub_byte (voidptr (& a.val), u8 (delta))
209
+ return T (old)
187
210
} $else $if T is u16 || T is i16 {
188
- C.atomic_fetch_sub_u16 (voidptr (& a.val), delta)
211
+ old := C.atomic_fetch_sub_u16 (voidptr (& a.val), u16 (delta))
212
+ return T (old)
189
213
} $else $if T is u32 || T is i32 {
190
- C.atomic_fetch_sub_u32 (voidptr (& a.val), delta)
214
+ old := C.atomic_fetch_sub_u32 (voidptr (& a.val), u32 (delta))
215
+ return T (old)
191
216
} $else $if T is u64 || T is i64 {
192
- C.atomic_fetch_sub_u64 (voidptr (& a.val), delta)
217
+ old := C.atomic_fetch_sub_u64 (voidptr (& a.val), u64 (delta))
218
+ return T (old)
193
219
} $else $if T is int {
194
- // TODO: remove this test or a compile time support $if sizeof() ==
195
220
if sizeof (int ) == 4 {
196
- C.atomic_fetch_sub_u32 (voidptr (& a.val), delta)
221
+ old := C.atomic_fetch_sub_u32 (voidptr (& a.val), u32 (delta))
222
+ return T (old)
197
223
} else {
198
- C.atomic_fetch_sub_u64 (voidptr (& a.val), delta)
224
+ old := C.atomic_fetch_sub_u64 (voidptr (& a.val), u64 (delta))
225
+ return T (old)
199
226
}
200
227
} $else $if T is isize || T is usize {
201
- // TODO: remove this test or a compile time support $if sizeof() ==
202
228
if sizeof (isize) == 4 {
203
- C.atomic_fetch_sub_u32 (voidptr (& a.val), delta)
229
+ old := C.atomic_fetch_sub_u32 (voidptr (& a.val), u32 (delta))
230
+ return T (old)
231
+ } else {
232
+ old := C.atomic_fetch_sub_u64 (voidptr (& a.val), u64 (delta))
233
+ return T (old)
234
+ }
235
+ }
236
+ panic ('unreachable' )
237
+ }
238
+
239
+ // swap sets the `new` value and returns the previous value
240
+ @[inline]
241
+ pub fn (mut a AtomicVal[T]) swap (new T) T {
242
+ $if T is bool {
243
+ old := C.atomic_exchange_byte (voidptr (& a.val), u8 (new))
244
+ return old != 0
245
+ } $else $if T is u8 || T is i8 {
246
+ old := C.atomic_exchange_byte (voidptr (& a.val), u8 (new))
247
+ return T (old)
248
+ } $else $if T is u16 || T is i16 {
249
+ old := C.atomic_exchange_u16 (voidptr (& a.val), u16 (new))
250
+ return T (old)
251
+ } $else $if T is u32 || T is i32 {
252
+ old := C.atomic_exchange_u32 (voidptr (& a.val), u32 (new))
253
+ return T (old)
254
+ } $else $if T is u64 || T is i64 {
255
+ old := C.atomic_exchange_u64 (voidptr (& a.val), u64 (new))
256
+ return T (old)
257
+ } $else $if T is int {
258
+ if sizeof (int ) == 4 {
259
+ old := C.atomic_exchange_u32 (voidptr (& a.val), u32 (new))
260
+ return T (old)
204
261
} else {
205
- C.atomic_fetch_sub_u64 (voidptr (& a.val), delta)
262
+ old := C.atomic_exchange_u64 (voidptr (& a.val), u64 (new))
263
+ return T (old)
264
+ }
265
+ } $else $if T is isize || T is usize {
266
+ if sizeof (isize) == 4 {
267
+ old := C.atomic_exchange_u32 (voidptr (& a.val), u32 (new))
268
+ return T (old)
269
+ } else {
270
+ old := C.atomic_exchange_u64 (voidptr (& a.val), u64 (new))
271
+ return T (old)
272
+ }
273
+ } $else $if T is voidptr {
274
+ // TODO: this should be $if sizeof(T) == 4
275
+ $if x32 {
276
+ old := C.atomic_exchange_u32 (voidptr (& a.val), u32 (new))
277
+ return T (old)
278
+ } $else {
279
+ old := C.atomic_exchange_u64 (voidptr (& a.val), u64 (new))
280
+ return T (old)
281
+ }
282
+ }
283
+ panic ('unreachable' )
284
+ }
285
+
286
+ // compare_and_swap executes the compare-and-swap(CAS) operation
287
+ // if atomic value == `expected`, then it will be set to `new`, and return true
288
+ // else return false, and the atomic value remains unchanged
289
+ @[inline]
290
+ pub fn (mut a AtomicVal[T]) compare_and_swap (expected T, new T) bool {
291
+ $if T is bool {
292
+ mut exp := u8 (expected)
293
+ return C.atomic_compare_exchange_strong_byte (voidptr (& a.val), & exp, u8 (new))
294
+ } $else $if T is u8 || T is i8 {
295
+ mut exp := u8 (expected)
296
+ return C.atomic_compare_exchange_strong_byte (voidptr (& a.val), & exp, u8 (new))
297
+ } $else $if T is u16 || T is i16 {
298
+ mut exp := u16 (expected)
299
+ return C.atomic_compare_exchange_strong_u16 (voidptr (& a.val), & exp, u16 (new))
300
+ } $else $if T is u32 || T is i32 {
301
+ mut exp := u32 (expected)
302
+ return C.atomic_compare_exchange_strong_u32 (voidptr (& a.val), & exp, u32 (new))
303
+ } $else $if T is u64 || T is i64 {
304
+ mut exp := u64 (expected)
305
+ return C.atomic_compare_exchange_strong_u64 (voidptr (& a.val), & exp, u64 (new))
306
+ } $else $if T is int {
307
+ if sizeof (int ) == 4 {
308
+ mut exp := u32 (expected)
309
+ return C.atomic_compare_exchange_strong_u32 (voidptr (& a.val), & exp, u32 (new))
310
+ } else {
311
+ mut exp := u64 (expected)
312
+ return C.atomic_compare_exchange_strong_u64 (voidptr (& a.val), & exp, u64 (new))
313
+ }
314
+ } $else $if T is isize || T is usize {
315
+ if sizeof (isize) == 4 {
316
+ mut exp := u32 (expected)
317
+ return C.atomic_compare_exchange_strong_u32 (voidptr (& a.val), & exp, u32 (new))
318
+ } else {
319
+ mut exp := u64 (expected)
320
+ return C.atomic_compare_exchange_strong_u64 (voidptr (& a.val), & exp, u64 (new))
321
+ }
322
+ } $else $if T is voidptr {
323
+ // TODO: this should be $if sizeof(T) == 4
324
+ $if x32 {
325
+ mut exp := u32 (expected)
326
+ return C.atomic_compare_exchange_strong_u32 (voidptr (& a.val), & exp, u32 (new))
327
+ } $else {
328
+ mut exp := u64 (expected)
329
+ return C.atomic_compare_exchange_strong_u64 (voidptr (& a.val), & exp, u64 (new))
206
330
}
207
331
}
208
- return T (a.val )
332
+ panic ( 'unreachable' )
209
333
}
0 commit comments