diff options
Diffstat (limited to 'tests/stdlib/concurrency')
-rw-r--r-- | tests/stdlib/concurrency/tatomics.nim | 609 |
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 |