Skip to content

Commit febc58e

Browse files
authored
allow C atomics on C++ with -d:nimUseCAtomics (#24207)
refs #24200 (comment) Workaround for C++ Atomic[T] issues that doesn't require a compiler change. Not tested or documented in case it's not meant to be officially supported, locally tested `tatomics` and #24159 to work with it though, can add these as tests if required.
1 parent b0e6d28 commit febc58e

File tree

1 file changed

+40
-25
lines changed

1 file changed

+40
-25
lines changed

lib/pure/concurrency/atomics.nim

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,7 @@ runnableExamples:
5050
flag.clear(moRelaxed)
5151
assert not flag.testAndSet
5252

53-
54-
when defined(cpp) or defined(nimdoc):
53+
when (defined(cpp) and not defined(nimUseCAtomics)) or defined(nimdoc):
5554
# For the C++ backend, types and operations map directly to C++11 atomics.
5655

5756
{.push, header: "<atomic>".}
@@ -274,27 +273,43 @@ else:
274273
cast[T](interlockedXor(addr(location.value), cast[nonAtomicType(T)](value)))
275274

276275
else:
277-
{.push, header: "<stdatomic.h>".}
276+
when defined(cpp):
277+
{.push, header: "<atomic>".}
278+
template maybeWrapStd(x: string): string =
279+
"std::" & x
280+
else:
281+
{.push, header: "<stdatomic.h>".}
282+
template maybeWrapStd(x: string): string =
283+
x
278284

279285
type
280-
MemoryOrder* {.importc: "memory_order".} = enum
286+
MemoryOrder* {.importc: "memory_order".maybeWrapStd.} = enum
281287
moRelaxed
282288
moConsume
283289
moAcquire
284290
moRelease
285291
moAcquireRelease
286292
moSequentiallyConsistent
287293

288-
type
289-
# Atomic*[T] {.importcpp: "_Atomic('0)".} = object
294+
when defined(cpp):
295+
type
296+
# Atomic*[T] {.importcpp: "_Atomic('0)".} = object
297+
298+
AtomicInt8 {.importc: "std::atomic<NI8>".} = int8
299+
AtomicInt16 {.importc: "std::atomic<NI16>".} = int16
300+
AtomicInt32 {.importc: "std::atomic<NI32>".} = int32
301+
AtomicInt64 {.importc: "std::atomic<NI64>".} = int64
302+
else:
303+
type
304+
# Atomic*[T] {.importcpp: "_Atomic('0)".} = object
290305

291-
AtomicInt8 {.importc: "_Atomic NI8".} = int8
292-
AtomicInt16 {.importc: "_Atomic NI16".} = int16
293-
AtomicInt32 {.importc: "_Atomic NI32".} = int32
294-
AtomicInt64 {.importc: "_Atomic NI64".} = int64
306+
AtomicInt8 {.importc: "_Atomic NI8".} = int8
307+
AtomicInt16 {.importc: "_Atomic NI16".} = int16
308+
AtomicInt32 {.importc: "_Atomic NI32".} = int32
309+
AtomicInt64 {.importc: "_Atomic NI64".} = int64
295310

296311
type
297-
AtomicFlag* {.importc: "atomic_flag", size: 1.} = object
312+
AtomicFlag* {.importc: "atomic_flag".maybeWrapStd, size: 1.} = object
298313

299314
Atomic*[T] = object
300315
when T is Trivial:
@@ -308,27 +323,27 @@ else:
308323
guard: AtomicFlag
309324

310325
#proc init*[T](location: var Atomic[T]; value: T): T {.importcpp: "atomic_init(@)".}
311-
proc atomic_load_explicit[T, A](location: ptr A; order: MemoryOrder): T {.importc.}
312-
proc atomic_store_explicit[T, A](location: ptr A; desired: T; order: MemoryOrder = moSequentiallyConsistent) {.importc.}
313-
proc atomic_exchange_explicit[T, A](location: ptr A; desired: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc.}
314-
proc atomic_compare_exchange_strong_explicit[T, A](location: ptr A; expected: ptr T; desired: T; success, failure: MemoryOrder): bool {.importc.}
315-
proc atomic_compare_exchange_weak_explicit[T, A](location: ptr A; expected: ptr T; desired: T; success, failure: MemoryOrder): bool {.importc.}
326+
proc atomic_load_explicit[T, A](location: ptr A; order: MemoryOrder): T {.importc: "atomic_load_explicit".maybeWrapStd.}
327+
proc atomic_store_explicit[T, A](location: ptr A; desired: T; order: MemoryOrder = moSequentiallyConsistent) {.importc: "atomic_store_explicit".maybeWrapStd.}
328+
proc atomic_exchange_explicit[T, A](location: ptr A; desired: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc: "atomic_exchange_explicit".maybeWrapStd.}
329+
proc atomic_compare_exchange_strong_explicit[T, A](location: ptr A; expected: ptr T; desired: T; success, failure: MemoryOrder): bool {.importc: "atomic_compare_exchange_strong_explicit".maybeWrapStd.}
330+
proc atomic_compare_exchange_weak_explicit[T, A](location: ptr A; expected: ptr T; desired: T; success, failure: MemoryOrder): bool {.importc: "atomic_compare_exchange_weak_explicit".maybeWrapStd.}
316331
317332
# Numerical operations
318-
proc atomic_fetch_add_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc.}
319-
proc atomic_fetch_sub_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc.}
320-
proc atomic_fetch_and_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc.}
321-
proc atomic_fetch_or_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc.}
322-
proc atomic_fetch_xor_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc.}
333+
proc atomic_fetch_add_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc: "atomic_fetch_add_explicit".maybeWrapStd.}
334+
proc atomic_fetch_sub_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc: "atomic_fetch_sub_explicit".maybeWrapStd.}
335+
proc atomic_fetch_and_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc: "atomic_fetch_and_explicit".maybeWrapStd.}
336+
proc atomic_fetch_or_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc: "atomic_fetch_or_explicit".maybeWrapStd.}
337+
proc atomic_fetch_xor_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc: "atomic_fetch_xor_explicit".maybeWrapStd.}
323338
324339
# Flag operations
325340
# var ATOMIC_FLAG_INIT {.importc, nodecl.}: AtomicFlag
326341
# proc init*(location: var AtomicFlag) {.inline.} = location = ATOMIC_FLAG_INIT
327-
proc testAndSet*(location: var AtomicFlag; order: MemoryOrder = moSequentiallyConsistent): bool {.importc: "atomic_flag_test_and_set_explicit".}
328-
proc clear*(location: var AtomicFlag; order: MemoryOrder = moSequentiallyConsistent) {.importc: "atomic_flag_clear_explicit".}
342+
proc testAndSet*(location: var AtomicFlag; order: MemoryOrder = moSequentiallyConsistent): bool {.importc: "atomic_flag_test_and_set_explicit".maybeWrapStd.}
343+
proc clear*(location: var AtomicFlag; order: MemoryOrder = moSequentiallyConsistent) {.importc: "atomic_flag_clear_explicit".maybeWrapStd.}
329344
330-
proc fence*(order: MemoryOrder) {.importc: "atomic_thread_fence".}
331-
proc signalFence*(order: MemoryOrder) {.importc: "atomic_signal_fence".}
345+
proc fence*(order: MemoryOrder) {.importc: "atomic_thread_fence".maybeWrapStd.}
346+
proc signalFence*(order: MemoryOrder) {.importc: "atomic_signal_fence".maybeWrapStd.}
332347
333348
{.pop.}
334349

0 commit comments

Comments
 (0)