summary refs log tree commit diff stats
path: root/tests/stdlib/concurrency
diff options
context:
space:
mode:
Diffstat (limited to 'tests/stdlib/concurrency')
-rw-r--r--tests/stdlib/concurrency/tatomics.nim609
1 files changed, 609 insertions, 0 deletions
diff --git a/tests/stdlib/concurrency/tatomics.nim b/tests/stdlib/concurrency/tatomics.nim
new file mode 100644
index 000000000..260d00990
--- /dev/null
+++ b/tests/stdlib/concurrency/tatomics.nim
@@ -0,0 +1,609 @@
+# test atomic operations
+
+import atomics, bitops
+
+type
+  Object = object
+    val: int
+
+
+# Atomic operations for trivial objects
+
+
+block trivialLoad:
+  var location: Atomic[int]
+  location.store(1)
+  doAssert location.load == 1
+  location.store(2)
+  doAssert location.load(moRelaxed) == 2
+  location.store(3)
+  doAssert location.load(moAcquire) == 3
+
+
+block trivialStore:
+  var location: Atomic[int]
+  location.store(1)
+  doAssert location.load == 1
+  location.store(2, moRelaxed)
+  doAssert location.load == 2
+  location.store(3, moRelease)
+  doAssert location.load == 3
+
+
+block trivialExchange:
+  var location: Atomic[int]
+  location.store(1)
+  doAssert location.exchange(2) == 1
+  doAssert location.exchange(3, moRelaxed) == 2
+  doAssert location.exchange(4, moAcquire) == 3
+  doAssert location.exchange(5, moRelease) == 4
+  doAssert location.exchange(6, moAcquireRelease) == 5
+  doAssert location.load == 6
+
+
+block trivialCompareExchangeDoesExchange:
+  var location: Atomic[int]
+  var expected = 1
+  location.store(1)
+  doAssert location.compareExchange(expected, 2)
+  doAssert expected == 1
+  doAssert location.load == 2
+  expected = 2
+  doAssert location.compareExchange(expected, 3, moRelaxed)
+  doAssert expected == 2
+  doAssert location.load == 3
+  expected = 3
+  doAssert location.compareExchange(expected, 4, moAcquire)
+  doAssert expected == 3
+  doAssert location.load == 4
+  expected = 4
+  doAssert location.compareExchange(expected, 5, moRelease)
+  doAssert expected == 4
+  doAssert location.load == 5
+  expected = 5
+  doAssert location.compareExchange(expected, 6, moAcquireRelease)
+  doAssert expected == 5
+  doAssert location.load == 6
+
+
+block trivialCompareExchangeDoesNotExchange:
+  var location: Atomic[int]
+  var expected = 10
+  location.store(1)
+  doAssert not location.compareExchange(expected, 2)
+  doAssert expected == 1
+  doAssert location.load == 1
+  expected = 10
+  doAssert not location.compareExchange(expected, 3, moRelaxed)
+  doAssert expected == 1
+  doAssert location.load == 1
+  expected = 10
+  doAssert not location.compareExchange(expected, 4, moAcquire)
+  doAssert expected == 1
+  doAssert location.load == 1
+  expected = 10
+  doAssert not location.compareExchange(expected, 5, moRelease)
+  doAssert expected == 1
+  doAssert location.load == 1
+  expected = 10
+  doAssert not location.compareExchange(expected, 6, moAcquireRelease)
+  doAssert expected == 1
+  doAssert location.load == 1
+
+
+block trivialCompareExchangeSuccessFailureDoesExchange:
+  var location: Atomic[int]
+  var expected = 1
+  location.store(1)
+  doAssert location.compareExchange(expected, 2, moSequentiallyConsistent, moSequentiallyConsistent)
+  doAssert expected == 1
+  doAssert location.load == 2
+  expected = 2
+  doAssert location.compareExchange(expected, 3, moRelaxed, moRelaxed)
+  doAssert expected == 2
+  doAssert location.load == 3
+  expected = 3
+  doAssert location.compareExchange(expected, 4, moAcquire, moAcquire)
+  doAssert expected == 3
+  doAssert location.load == 4
+  expected = 4
+  doAssert location.compareExchange(expected, 5, moRelease, moRelease)
+  doAssert expected == 4
+  doAssert location.load == 5
+  expected = 5
+  doAssert location.compareExchange(expected, 6, moAcquireRelease, moAcquireRelease)
+  doAssert expected == 5
+  doAssert location.load == 6
+
+
+block trivialCompareExchangeSuccessFailureDoesNotExchange:
+  var location: Atomic[int]
+  var expected = 10
+  location.store(1)
+  doAssert not location.compareExchange(expected, 2, moSequentiallyConsistent, moSequentiallyConsistent)
+  doAssert expected == 1
+  doAssert location.load == 1
+  expected = 10
+  doAssert not location.compareExchange(expected, 3, moRelaxed, moRelaxed)
+  doAssert expected == 1
+  doAssert location.load == 1
+  expected = 10
+  doAssert not location.compareExchange(expected, 4, moAcquire, moAcquire)
+  doAssert expected == 1
+  doAssert location.load == 1
+  expected = 10
+  doAssert not location.compareExchange(expected, 5, moRelease, moRelease)
+  doAssert expected == 1
+  doAssert location.load == 1
+  expected = 10
+  doAssert not location.compareExchange(expected, 6, moAcquireRelease, moAcquireRelease)
+  doAssert expected == 1
+  doAssert location.load == 1
+
+
+block trivialCompareExchangeWeakDoesExchange:
+  var location: Atomic[int]
+  var expected = 1
+  location.store(1)
+  doAssert location.compareExchangeWeak(expected, 2)
+  doAssert expected == 1
+  doAssert location.load == 2
+  expected = 2
+  doAssert location.compareExchangeWeak(expected, 3, moRelaxed)
+  doAssert expected == 2
+  doAssert location.load == 3
+  expected = 3
+  doAssert location.compareExchangeWeak(expected, 4, moAcquire)
+  doAssert expected == 3
+  doAssert location.load == 4
+  expected = 4
+  doAssert location.compareExchangeWeak(expected, 5, moRelease)
+  doAssert expected == 4
+  doAssert location.load == 5
+  expected = 5
+  doAssert location.compareExchangeWeak(expected, 6, moAcquireRelease)
+  doAssert expected == 5
+  doAssert location.load == 6
+
+
+block trivialCompareExchangeWeakDoesNotExchange:
+  var location: Atomic[int]
+  var expected = 10
+  location.store(1)
+  doAssert not location.compareExchangeWeak(expected, 2)
+  doAssert expected == 1
+  doAssert location.load == 1
+  expected = 10
+  doAssert not location.compareExchangeWeak(expected, 3, moRelaxed)
+  doAssert expected == 1
+  doAssert location.load == 1
+  expected = 10
+  doAssert not location.compareExchangeWeak(expected, 4, moAcquire)
+  doAssert expected == 1
+  doAssert location.load == 1
+  expected = 10
+  doAssert not location.compareExchangeWeak(expected, 5, moRelease)
+  doAssert expected == 1
+  doAssert location.load == 1
+  expected = 10
+  doAssert not location.compareExchangeWeak(expected, 6, moAcquireRelease)
+  doAssert expected == 1
+  doAssert location.load == 1
+
+
+block trivialCompareExchangeWeakSuccessFailureDoesExchange:
+  var location: Atomic[int]
+  var expected = 1
+  location.store(1)
+  doAssert location.compareExchangeWeak(expected, 2, moSequentiallyConsistent, moSequentiallyConsistent)
+  doAssert expected == 1
+  doAssert location.load == 2
+  expected = 2
+  doAssert location.compareExchangeWeak(expected, 3, moRelaxed, moRelaxed)
+  doAssert expected == 2
+  doAssert location.load == 3
+  expected = 3
+  doAssert location.compareExchangeWeak(expected, 4, moAcquire, moAcquire)
+  doAssert expected == 3
+  doAssert location.load == 4
+  expected = 4
+  doAssert location.compareExchangeWeak(expected, 5, moRelease, moRelease)
+  doAssert expected == 4
+  doAssert location.load == 5
+  expected = 5
+  doAssert location.compareExchangeWeak(expected, 6, moAcquireRelease, moAcquireRelease)
+  doAssert expected == 5
+  doAssert location.load == 6
+
+
+block trivialCompareExchangeWeakSuccessFailureDoesNotExchange:
+  var location: Atomic[int]
+  var expected = 10
+  location.store(1)
+  doAssert not location.compareExchangeWeak(expected, 2, moSequentiallyConsistent, moSequentiallyConsistent)
+  doAssert expected == 1
+  doAssert location.load == 1
+  expected = 10
+  doAssert not location.compareExchangeWeak(expected, 3, moRelaxed, moRelaxed)
+  doAssert expected == 1
+  doAssert location.load == 1
+  expected = 10
+  doAssert not location.compareExchangeWeak(expected, 4, moAcquire, moAcquire)
+  doAssert expected == 1
+  doAssert location.load == 1
+  expected = 10
+  doAssert not location.compareExchangeWeak(expected, 5, moRelease, moRelease)
+  doAssert expected == 1
+  doAssert location.load == 1
+  expected = 10
+  doAssert not location.compareExchangeWeak(expected, 6, moAcquireRelease, moAcquireRelease)
+  doAssert expected == 1
+  doAssert location.load == 1
+
+
+# Atomic operations for non-trivial objects
+
+
+block objectLoad:
+  var location: Atomic[Object]
+  location.store(Object(val: 1))
+  doAssert location.load == Object(val: 1)
+  location.store(Object(val: 2))
+  doAssert location.load(moRelaxed) == Object(val: 2)
+  location.store(Object(val: 3))
+  doAssert location.load(moAcquire) == Object(val: 3)
+
+
+block objectStore:
+  var location: Atomic[Object]
+  location.store(Object(val: 1))
+  doAssert location.load == Object(val: 1)
+  location.store(Object(val: 2), moRelaxed)
+  doAssert location.load == Object(val: 2)
+  location.store(Object(val: 3), moRelease)
+  doAssert location.load == Object(val: 3)
+
+
+block objectExchange:
+  var location: Atomic[Object]
+  location.store(Object(val: 1))
+  doAssert location.exchange(Object(val: 2)) == Object(val: 1)
+  doAssert location.exchange(Object(val: 3), moRelaxed) == Object(val: 2)
+  doAssert location.exchange(Object(val: 4), moAcquire) == Object(val: 3)
+  doAssert location.exchange(Object(val: 5), moRelease) == Object(val: 4)
+  doAssert location.exchange(Object(val: 6), moAcquireRelease) == Object(val: 5)
+  doAssert location.load == Object(val: 6)
+
+
+block objectCompareExchangeDoesExchange:
+  var location: Atomic[Object]
+  var expected = Object(val: 1)
+  location.store(Object(val: 1))
+  doAssert location.compareExchange(expected, Object(val: 2))
+  doAssert expected == Object(val: 1)
+  doAssert location.load == Object(val: 2)
+  expected = Object(val: 2)
+  doAssert location.compareExchange(expected, Object(val: 3), moRelaxed)
+  doAssert expected == Object(val: 2)
+  doAssert location.load == Object(val: 3)
+  expected = Object(val: 3)
+  doAssert location.compareExchange(expected, Object(val: 4), moAcquire)
+  doAssert expected == Object(val: 3)
+  doAssert location.load == Object(val: 4)
+  expected = Object(val: 4)
+  doAssert location.compareExchange(expected, Object(val: 5), moRelease)
+  doAssert expected == Object(val: 4)
+  doAssert location.load == Object(val: 5)
+  expected = Object(val: 5)
+  doAssert location.compareExchange(expected, Object(val: 6), moAcquireRelease)
+  doAssert expected == Object(val: 5)
+  doAssert location.load == Object(val: 6)
+
+
+block objectCompareExchangeDoesNotExchange:
+  var location: Atomic[Object]
+  var expected = Object(val: 10)
+  location.store(Object(val: 1))
+  doAssert not location.compareExchange(expected, Object(val: 2))
+  doAssert expected == Object(val: 1)
+  doAssert location.load == Object(val: 1)
+  expected = Object(val: 10)
+  doAssert not location.compareExchange(expected, Object(val: 3), moRelaxed)
+  doAssert expected == Object(val: 1)
+  doAssert location.load == Object(val: 1)
+  expected = Object(val: 10)
+  doAssert not location.compareExchange(expected, Object(val: 4), moAcquire)
+  doAssert expected == Object(val: 1)
+  doAssert location.load == Object(val: 1)
+  expected = Object(val: 10)
+  doAssert not location.compareExchange(expected, Object(val: 5), moRelease)
+  doAssert expected == Object(val: 1)
+  doAssert location.load == Object(val: 1)
+  expected = Object(val: 10)
+  doAssert not location.compareExchange(expected, Object(val: 6), moAcquireRelease)
+  doAssert expected == Object(val: 1)
+  doAssert location.load == Object(val: 1)
+
+
+block objectCompareExchangeSuccessFailureDoesExchange:
+  var location: Atomic[Object]
+  var expected = Object(val: 1)
+  location.store(Object(val: 1))
+  doAssert location.compareExchange(expected, Object(val: 2), moSequentiallyConsistent, moSequentiallyConsistent)
+  doAssert expected == Object(val: 1)
+  doAssert location.load == Object(val: 2)
+  expected = Object(val: 2)
+  doAssert location.compareExchange(expected, Object(val: 3), moRelaxed, moRelaxed)
+  doAssert expected == Object(val: 2)
+  doAssert location.load == Object(val: 3)
+  expected = Object(val: 3)
+  doAssert location.compareExchange(expected, Object(val: 4), moAcquire, moAcquire)
+  doAssert expected == Object(val: 3)
+  doAssert location.load == Object(val: 4)
+  expected = Object(val: 4)
+  doAssert location.compareExchange(expected, Object(val: 5), moRelease, moRelease)
+  doAssert expected == Object(val: 4)
+  doAssert location.load == Object(val: 5)
+  expected = Object(val: 5)
+  doAssert location.compareExchange(expected, Object(val: 6), moAcquireRelease, moAcquireRelease)
+  doAssert expected == Object(val: 5)
+  doAssert location.load == Object(val: 6)
+
+
+block objectCompareExchangeSuccessFailureDoesNotExchange:
+  var location: Atomic[Object]
+  var expected = Object(val: 10)
+  location.store(Object(val: 1))
+  doAssert not location.compareExchange(expected, Object(val: 2), moSequentiallyConsistent, moSequentiallyConsistent)
+  doAssert expected == Object(val: 1)
+  doAssert location.load == Object(val: 1)
+  expected = Object(val: 10)
+  doAssert not location.compareExchange(expected, Object(val: 3), moRelaxed, moRelaxed)
+  doAssert expected == Object(val: 1)
+  doAssert location.load == Object(val: 1)
+  expected = Object(val: 10)
+  doAssert not location.compareExchange(expected, Object(val: 4), moAcquire, moAcquire)
+  doAssert expected == Object(val: 1)
+  doAssert location.load == Object(val: 1)
+  expected = Object(val: 10)
+  doAssert not location.compareExchange(expected, Object(val: 5), moRelease, moRelease)
+  doAssert expected == Object(val: 1)
+  doAssert location.load == Object(val: 1)
+  expected = Object(val: 10)
+  doAssert not location.compareExchange(expected, Object(val: 6), moAcquireRelease, moAcquireRelease)
+  doAssert expected == Object(val: 1)
+  doAssert location.load == Object(val: 1)
+
+
+block objectCompareExchangeWeakDoesExchange:
+  var location: Atomic[Object]
+  var expected = Object(val: 1)
+  location.store(Object(val: 1))
+  doAssert location.compareExchangeWeak(expected, Object(val: 2))
+  doAssert expected == Object(val: 1)
+  doAssert location.load == Object(val: 2)
+  expected = Object(val: 2)
+  doAssert location.compareExchangeWeak(expected, Object(val: 3), moRelaxed)
+  doAssert expected == Object(val: 2)
+  doAssert location.load == Object(val: 3)
+  expected = Object(val: 3)
+  doAssert location.compareExchangeWeak(expected, Object(val: 4), moAcquire)
+  doAssert expected == Object(val: 3)
+  doAssert location.load == Object(val: 4)
+  expected = Object(val: 4)
+  doAssert location.compareExchangeWeak(expected, Object(val: 5), moRelease)
+  doAssert expected == Object(val: 4)
+  doAssert location.load == Object(val: 5)
+  expected = Object(val: 5)
+  doAssert location.compareExchangeWeak(expected, Object(val: 6), moAcquireRelease)
+  doAssert expected == Object(val: 5)
+  doAssert location.load == Object(val: 6)
+
+
+block objectCompareExchangeWeakDoesNotExchange:
+  var location: Atomic[Object]
+  var expected = Object(val: 10)
+  location.store(Object(val: 1))
+  doAssert not location.compareExchangeWeak(expected, Object(val: 2))
+  doAssert expected == Object(val: 1)
+  doAssert location.load == Object(val: 1)
+  expected = Object(val: 10)
+  doAssert not location.compareExchangeWeak(expected, Object(val: 3), moRelaxed)
+  doAssert expected == Object(val: 1)
+  doAssert location.load == Object(val: 1)
+  expected = Object(val: 10)
+  doAssert not location.compareExchangeWeak(expected, Object(val: 4), moAcquire)
+  doAssert expected == Object(val: 1)
+  doAssert location.load == Object(val: 1)
+  expected = Object(val: 10)
+  doAssert not location.compareExchangeWeak(expected, Object(val: 5), moRelease)
+  doAssert expected == Object(val: 1)
+  doAssert location.load == Object(val: 1)
+  expected = Object(val: 10)
+  doAssert not location.compareExchangeWeak(expected, Object(val: 6), moAcquireRelease)
+  doAssert expected == Object(val: 1)
+  doAssert location.load == Object(val: 1)
+
+
+block objectCompareExchangeWeakSuccessFailureDoesExchange:
+  var location: Atomic[Object]
+  var expected = Object(val: 1)
+  location.store(Object(val: 1))
+  doAssert location.compareExchangeWeak(expected, Object(val: 2), moSequentiallyConsistent, moSequentiallyConsistent)
+  doAssert expected == Object(val: 1)
+  doAssert location.load == Object(val: 2)
+  expected = Object(val: 2)
+  doAssert location.compareExchangeWeak(expected, Object(val: 3), moRelaxed, moRelaxed)
+  doAssert expected == Object(val: 2)
+  doAssert location.load == Object(val: 3)
+  expected = Object(val: 3)
+  doAssert location.compareExchangeWeak(expected, Object(val: 4), moAcquire, moAcquire)
+  doAssert expected == Object(val: 3)
+  doAssert location.load == Object(val: 4)
+  expected = Object(val: 4)
+  doAssert location.compareExchangeWeak(expected, Object(val: 5), moRelease, moRelease)
+  doAssert expected == Object(val: 4)
+  doAssert location.load == Object(val: 5)
+  expected = Object(val: 5)
+  doAssert location.compareExchangeWeak(expected, Object(val: 6), moAcquireRelease, moAcquireRelease)
+  doAssert expected == Object(val: 5)
+  doAssert location.load == Object(val: 6)
+
+
+block objectCompareExchangeWeakSuccessFailureDoesNotExchange:
+  var location: Atomic[Object]
+  var expected = Object(val: 10)
+  location.store(Object(val: 1))
+  doAssert not location.compareExchangeWeak(expected, Object(val: 2), moSequentiallyConsistent, moSequentiallyConsistent)
+  doAssert expected == Object(val: 1)
+  doAssert location.load == Object(val: 1)
+  expected = Object(val: 10)
+  doAssert not location.compareExchangeWeak(expected, Object(val: 3), moRelaxed, moRelaxed)
+  doAssert expected == Object(val: 1)
+  doAssert location.load == Object(val: 1)
+  expected = Object(val: 10)
+  doAssert not location.compareExchangeWeak(expected, Object(val: 4), moAcquire, moAcquire)
+  doAssert expected == Object(val: 1)
+  doAssert location.load == Object(val: 1)
+  expected = Object(val: 10)
+  doAssert not location.compareExchangeWeak(expected, Object(val: 5), moRelease, moRelease)
+  doAssert expected == Object(val: 1)
+  doAssert location.load == Object(val: 1)
+  expected = Object(val: 10)
+  doAssert not location.compareExchangeWeak(expected, Object(val: 6), moAcquireRelease, moAcquireRelease)
+  doAssert expected == Object(val: 1)
+  doAssert location.load == Object(val: 1)
+
+
+# Numerical operations
+
+
+block fetchAdd:
+  var location: Atomic[int]
+  doAssert location.fetchAdd(1) == 0
+  doAssert location.fetchAdd(1, moRelaxed) == 1
+  doAssert location.fetchAdd(1, moRelease) == 2
+  doAssert location.load == 3
+
+
+block fetchSub:
+  var location: Atomic[int]
+  doAssert location.fetchSub(1) == 0
+  doAssert location.fetchSub(1, moRelaxed) == -1
+  doAssert location.fetchSub(1, moRelease) == -2
+  doAssert location.load == -3
+
+
+block fetchAnd:
+  var location: Atomic[int]
+
+  for i in 0..16:
+    for j in 0..16:
+      location.store(i)
+      doAssert(location.fetchAnd(j) == i)
+      doAssert(location.load == i.bitand(j))
+
+  for i in 0..16:
+    for j in 0..16:
+      location.store(i)
+      doAssert(location.fetchAnd(j, moRelaxed) == i)
+      doAssert(location.load == i.bitand(j))
+
+  for i in 0..16:
+    for j in 0..16:
+      location.store(i)
+      doAssert(location.fetchAnd(j, moRelease) == i)
+      doAssert(location.load == i.bitand(j))
+
+
+block fetchOr:
+  var location: Atomic[int]
+
+  for i in 0..16:
+    for j in 0..16:
+      location.store(i)
+      doAssert(location.fetchOr(j) == i)
+      doAssert(location.load == i.bitor(j))
+
+  for i in 0..16:
+    for j in 0..16:
+      location.store(i)
+      doAssert(location.fetchOr(j, moRelaxed) == i)
+      doAssert(location.load == i.bitor(j))
+
+  for i in 0..16:
+    for j in 0..16:
+      location.store(i)
+      doAssert(location.fetchOr(j, moRelease) == i)
+      doAssert(location.load == i.bitor(j))
+
+
+block fetchXor:
+  var location: Atomic[int]
+
+  for i in 0..16:
+    for j in 0..16:
+      location.store(i)
+      doAssert(location.fetchXor(j) == i)
+      doAssert(location.load == i.bitxor(j))
+
+  for i in 0..16:
+    for j in 0..16:
+      location.store(i)
+      doAssert(location.fetchXor(j, moRelaxed) == i)
+      doAssert(location.load == i.bitxor(j))
+
+  for i in 0..16:
+    for j in 0..16:
+      location.store(i)
+      doAssert(location.fetchXor(j, moRelease) == i)
+      doAssert(location.load == i.bitxor(j))
+
+
+block atomicInc:
+  var location: Atomic[int]
+  location.atomicInc
+  doAssert location.load == 1
+  location.atomicInc(1)
+  doAssert location.load == 2
+  location += 1
+  doAssert location.load == 3
+
+
+block atomicDec:
+  var location: Atomic[int]
+  location.atomicDec
+  doAssert location.load == -1
+  location.atomicDec(1)
+  doAssert location.load == -2
+  location -= 1
+  doAssert location.load == -3
+
+
+# Flag operations
+
+
+block testAndSet:
+  var location: AtomicFlag
+  doAssert not location.testAndSet
+  doAssert location.testAndSet
+  doAssert location.testAndSet
+  location.clear()
+  doAssert not location.testAndSet(moRelaxed)
+  doAssert location.testAndSet(moRelaxed)
+  doAssert location.testAndSet(moRelaxed)
+  location.clear()
+  doAssert not location.testAndSet(moRelease)
+  doAssert location.testAndSet(moRelease)
+  doAssert location.testAndSet(moRelease)
+
+
+block clear:
+  var location: AtomicFlag
+  discard location.testAndSet
+  location.clear
+  doAssert not location.testAndSet
+  location.clear(moRelaxed)
+  doAssert not location.testAndSet
+  location.clear(moRelease)
+  doAssert not location.testAndSet