# # # Nimrod's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # # Atomic operations for Nimrod. when (defined(gcc) or defined(llvm_gcc)) and hasThreadSupport and not defined(windows): proc sync_add_and_fetch(p: var int, val: int): int {. importc: "__sync_add_and_fetch", nodecl.} proc sync_sub_and_fetch(p: var int, val: int): int {. importc: "__sync_sub_and_fetch", nodecl.} elif defined(vcc) and hasThreadSupport: proc sync_add_and_fetch(p: var int, val: int): int {. importc: "NimXadd", nodecl.} else: proc sync_add_and_fetch(p: var int, val: int): int {.inline.} = inc(p, val) result = p proc atomicInc(memLoc: var int, x: int = 1): int = when hasThreadSupport: result = sync_add_and_fetch(memLoc, x) else: inc(memLoc, x) result = memLoc proc atomicDec(memLoc: var int, x: int = 1): int = when hasThreadSupport: when defined(sync_sub_and_fetch): result = sync_sub_and_fetch(memLoc, x) else: result = sync_add_and_fetch(memLoc, -x) else: dec(memLoc, x) result = memLoc # atomic compare and swap (CAS) funcitons to implement lock-free algorithms when (defined(gcc) or defined(llvm_gcc)) and hasThreadSupport: proc compareAndSwap*[T: ptr|ref|pointer](mem: var T, expected: T, newValue: T): bool {.nodecl, importc: " __sync_bool_compare_and_swap".} ## Returns true if successfully set value at mem to newValue when value ## at mem == expected elif defined(windows) and hasThreadSupport: proc InterlockedCompareExchangePointer(mem: ptr pointer, newValue: pointer, comparand: pointer) : pointer {.nodecl, importc: "InterlockedCompareExchangePointer", header:"windows.h".} proc compareAndSwap*[T: ptr|ref|pointer](mem: var T, expected: T, newValue: T): bool {.inline.}= ## Returns true if successfully set value at mem to newValue when value ## at mem == expected return InterlockedCompareExchangePointer(addr(mem), newValue, expected) == expected elif not hasThreadSupport: proc compareAndSwap*[T: ptr|ref|pointer](mem: var T, expected: T, newValue: T): bool {.inline.} = ## Returns true if successfully set value at mem to newValue when value ## at mem == expected var oldval = mem if oldval == expected: mem = newValue return true return false