| /* | |
| * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors. | |
| * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. | |
| */ | |
| @file:OptIn(ExperimentalAtomicApi::class) | |
| package test.concurrent.atomics | |
| import kotlin.concurrent.atomics.* | |
| import kotlin.test.* | |
| class AtomicIntTest { | |
| @Test | |
| fun ctor() { | |
| val x = AtomicInt(0) | |
| assertEquals(0, x.load()) | |
| } | |
| @Test | |
| fun setter() { | |
| val x = AtomicInt(0) | |
| x.store(1) | |
| assertEquals(1, x.load()) | |
| } | |
| @Test | |
| fun addAndGet() { | |
| val x = AtomicInt(1) | |
| val result = x.addAndFetch(2) | |
| assertEquals(1 + 2, result) | |
| assertEquals(result, x.load()) | |
| } | |
| @Test | |
| fun compareAndExchange() { | |
| val x = AtomicInt(0) | |
| val successValue = x.compareAndExchange(0, 1) | |
| assertEquals(0, successValue) | |
| assertEquals(1, x.load()) | |
| val failValue = x.compareAndExchange(0, 2) | |
| assertEquals(1, failValue) | |
| assertEquals(1, x.load()) | |
| } | |
| @Test | |
| fun compareAndSet() { | |
| val x = AtomicInt(0) | |
| val successValue = x.compareAndSet(0, 1) | |
| assertTrue(successValue) | |
| assertEquals(1, x.load()) | |
| val failValue = x.compareAndSet(0, 2) | |
| assertFalse(failValue) | |
| assertEquals(1, x.load()) | |
| } | |
| @Test | |
| fun smoke() { | |
| val atomic = AtomicInt(3) | |
| assertEquals(3, atomic.load()) | |
| atomic.store(5) | |
| assertEquals(5, atomic.load()) | |
| assertEquals(5, atomic.exchange(6)) | |
| assertEquals(6, atomic.load()) | |
| assertTrue(atomic.compareAndSet(6, 8)) | |
| assertFalse(atomic.compareAndSet(9, 1)) | |
| assertEquals(8, atomic.load()) | |
| assertEquals(8, atomic.fetchAndAdd(5)) | |
| assertEquals(13, atomic.load()) | |
| assertEquals(18, atomic.addAndFetch(5)) | |
| assertEquals(18, atomic.fetchAndIncrement()) | |
| assertEquals(19, atomic.load()) | |
| assertEquals(20, atomic.incrementAndFetch()) | |
| assertEquals(20, atomic.load()) | |
| assertEquals(20, atomic.fetchAndDecrement()) | |
| assertEquals(19, atomic.load()) | |
| assertEquals(18, atomic.decrementAndFetch()) | |
| assertEquals(18, atomic.load()) | |
| assertEquals(18, atomic.compareAndExchange(18, 56)) | |
| assertEquals(56, atomic.compareAndExchange(18, 56)) | |
| assertEquals(56, atomic.compareAndExchange(18, 56)) | |
| } | |
| @Test | |
| fun toStringTest() { | |
| assertEquals("42", AtomicInt(42).toString()) | |
| } | |
| @Test | |
| fun update() { | |
| val a = AtomicInt(0) | |
| a.update { cur -> cur + 4 } | |
| assertEquals(4, a.load()) | |
| a.update { cur -> cur * 2 } | |
| assertEquals(8, a.load()) | |
| a.update { cur -> cur } | |
| assertEquals(8, a.load()) | |
| } | |
| @Test | |
| fun updateAndGet() { | |
| val a = AtomicInt(0) | |
| assertEquals(4, a.updateAndFetch { cur -> cur + 4 }) | |
| assertEquals(4, a.load()) | |
| assertEquals(8, a.updateAndFetch { cur -> cur * 2 }) | |
| assertEquals(8, a.load()) | |
| assertEquals(8, a.updateAndFetch { cur -> cur }) | |
| assertEquals(8, a.load()) | |
| } | |
| @Test | |
| fun getAndUpdate() { | |
| val a = AtomicInt(0) | |
| assertEquals(0, a.fetchAndUpdate { cur -> cur + 4 }) | |
| assertEquals(4, a.load()) | |
| assertEquals(4, a.fetchAndUpdate { cur -> cur * 2 }) | |
| assertEquals(8, a.load()) | |
| assertEquals(8, a.fetchAndUpdate { cur -> cur }) | |
| assertEquals(8, a.load()) | |
| } | |
| } | |
| class AtomicLongTest { | |
| @Test | |
| fun ctor() { | |
| val x = AtomicLong(0) | |
| assertEquals(0, x.load()) | |
| } | |
| @Test | |
| fun setter() { | |
| val x = AtomicLong(0) | |
| x.store(1) | |
| assertEquals(1, x.load()) | |
| } | |
| @Test | |
| fun addAndGet() { | |
| val x = AtomicLong(1) | |
| val result = x.addAndFetch(2L) | |
| assertEquals(1 + 2, result) | |
| assertEquals(result, x.load()) | |
| } | |
| @Test | |
| fun compareAndExchange() { | |
| val x = AtomicLong(0) | |
| val successValue = x.compareAndExchange(0, 1) | |
| assertEquals(0, successValue) | |
| assertEquals(1, x.load()) | |
| val failValue = x.compareAndExchange(0, 2) | |
| assertEquals(1, failValue) | |
| assertEquals(1, x.load()) | |
| } | |
| @Test | |
| fun compareAndSet() { | |
| val x = AtomicLong(0) | |
| val successValue = x.compareAndSet(0, 1) | |
| assertTrue(successValue) | |
| assertEquals(1, x.load()) | |
| val failValue = x.compareAndSet(0, 2) | |
| assertFalse(failValue) | |
| assertEquals(1, x.load()) | |
| } | |
| @Test | |
| fun smoke() { | |
| val atomic = AtomicLong(1424920024888900000) | |
| assertEquals(1424920024888900000, atomic.load()) | |
| atomic.store(2424920024888900000) | |
| assertEquals(2424920024888900000, atomic.load()) | |
| assertEquals(2424920024888900000, atomic.exchange(3424920024888900000)) | |
| assertEquals(3424920024888900000, atomic.load()) | |
| assertTrue(atomic.compareAndSet(3424920024888900000, 4424920024888900000)) | |
| assertFalse(atomic.compareAndSet(9, 1)) | |
| assertEquals(4424920024888900000, atomic.load()) | |
| assertEquals(4424920024888900000, atomic.fetchAndAdd(100000)) | |
| assertEquals(4424920024889000000, atomic.load()) | |
| assertEquals(4424920024890000000, atomic.addAndFetch(1000000L)) | |
| assertEquals(4424920024890000000, atomic.fetchAndIncrement()) | |
| assertEquals(4424920024890000001, atomic.load()) | |
| assertEquals(4424920024890000002, atomic.incrementAndFetch()) | |
| assertEquals(4424920024890000002, atomic.load()) | |
| assertEquals(4424920024890000002, atomic.fetchAndDecrement()) | |
| assertEquals(4424920024890000001, atomic.load()) | |
| assertEquals(4424920024890000000, atomic.decrementAndFetch()) | |
| assertEquals(4424920024890000000, atomic.load()) | |
| assertEquals(4424920024890000000, atomic.compareAndExchange(4424920024890000000, 5424920024890000000)) | |
| assertEquals(5424920024890000000, atomic.compareAndExchange(18, 56)) | |
| assertEquals(5424920024890000000, atomic.compareAndExchange(18, 56)) | |
| } | |
| @Test | |
| fun toStringTest() { | |
| assertEquals("42", AtomicLong(42).toString()) | |
| } | |
| @Test | |
| fun update() { | |
| val a = AtomicLong(0) | |
| a.update { cur -> cur + 4 } | |
| assertEquals(4L, a.load()) | |
| a.update { cur -> cur * 2 } | |
| assertEquals(8L, a.load()) | |
| a.update { cur -> cur } | |
| assertEquals(8L, a.load()) | |
| } | |
| @Test | |
| fun updateAndGet() { | |
| val a = AtomicLong(0) | |
| assertEquals(4L, a.updateAndFetch { cur -> cur + 4 }) | |
| assertEquals(4L, a.load()) | |
| assertEquals(8L, a.updateAndFetch { cur -> cur * 2 }) | |
| assertEquals(8L, a.load()) | |
| assertEquals(8L, a.updateAndFetch { cur -> cur }) | |
| assertEquals(8L, a.load()) | |
| } | |
| @Test | |
| fun getAndUpdate() { | |
| val a = AtomicLong(0) | |
| assertEquals(0L, a.fetchAndUpdate { cur -> cur + 4 }) | |
| assertEquals(4L, a.load()) | |
| assertEquals(4L, a.fetchAndUpdate { cur -> cur * 2 }) | |
| assertEquals(8L, a.load()) | |
| assertEquals(8L, a.fetchAndUpdate { cur -> cur }) | |
| assertEquals(8L, a.load()) | |
| } | |
| } | |
| class AtomicBooleanTest { | |
| @Test | |
| fun ctor() { | |
| val x = AtomicBoolean(true) | |
| assertTrue(x.load()) | |
| } | |
| @Test | |
| fun setter() { | |
| val x = AtomicBoolean(true) | |
| x.store(false) | |
| assertFalse(x.load()) | |
| } | |
| @Test | |
| fun compareAndExchange() { | |
| val x = AtomicBoolean(true) | |
| val successValue = x.compareAndExchange(true, false) | |
| assertTrue(successValue) | |
| assertFalse(x.load()) | |
| val failValue = x.compareAndExchange(true, false) | |
| assertFalse(failValue) | |
| assertFalse(x.load()) | |
| } | |
| @Test | |
| fun compareAndSet() { | |
| val x = AtomicBoolean(true) | |
| val successValue = x.compareAndSet(true, false) | |
| assertTrue(successValue) | |
| assertFalse(x.load()) | |
| val failValue = x.compareAndSet(true, false) | |
| assertFalse(failValue) | |
| assertFalse(x.load()) | |
| } | |
| @Test | |
| fun exchange() { | |
| val atomic = AtomicBoolean(true) | |
| assertTrue(atomic.load()) | |
| atomic.store(false) | |
| assertFalse(atomic.load()) | |
| assertFalse(atomic.exchange(true)) | |
| assertTrue(atomic.load()) | |
| } | |
| @Test | |
| fun toStringTest() { | |
| assertEquals("true", AtomicBoolean(true).toString()) | |
| } | |
| } | |
| class AtomicReferenceTest { | |
| private data class Data(val value: Int) | |
| @Test | |
| fun ctor() { | |
| val x = AtomicReference(Data(1)) | |
| assertEquals(x.load(), Data(1)) | |
| } | |
| @Test | |
| fun setter() { | |
| val x = AtomicReference<Data>(Data(1)) | |
| x.store(Data(2)) | |
| assertEquals(x.load(), Data(2)) | |
| } | |
| @Test | |
| fun compareAndExchange() { | |
| val initial = Data(1) | |
| val new = Data(2) | |
| val x = AtomicReference<Data>(initial) | |
| val successValue = x.compareAndExchange(initial, new) | |
| assertEquals(successValue, initial) | |
| assertEquals(x.load(), new) | |
| val failValue = x.compareAndExchange(initial, Data(3)) | |
| assertEquals(failValue, new) | |
| assertEquals(x.load(), new) | |
| } | |
| @Test | |
| fun compareAndSet() { | |
| val initial = Data(1) | |
| val new = Data(2) | |
| val x = AtomicReference<Data>(initial) | |
| val successValue = x.compareAndSet(initial, new) | |
| assertTrue(successValue) | |
| assertEquals(x.load(), new) | |
| val failValue = x.compareAndSet(initial, Data(2)) | |
| assertFalse(failValue) | |
| assertEquals(x.load(), new) | |
| } | |
| @Test | |
| fun smoke() { | |
| val atomic = AtomicReference<List<Data>>(listOf(Data(1), Data(2), Data(3))) | |
| assertEquals(listOf(Data(1), Data(2), Data(3)), atomic.load()) | |
| atomic.store(listOf(Data(1), Data(2), Data(1))) | |
| assertEquals(listOf(Data(1), Data(2), Data(1)), atomic.load()) | |
| assertEquals(listOf(Data(1), Data(2), Data(1)), atomic.exchange(listOf(Data(1), Data(1), Data(1)))) | |
| assertEquals(listOf(Data(1), Data(1), Data(1)), atomic.load()) | |
| var cur = atomic.load() | |
| assertTrue(atomic.compareAndSet(cur, listOf(Data(2), Data(2), Data(2)))) | |
| assertFalse(atomic.compareAndSet(listOf(Data(1), Data(1), Data(1)), listOf(Data(2), Data(2), Data(2)))) | |
| assertEquals(listOf(Data(2), Data(2), Data(2)), atomic.load()) | |
| cur = atomic.load() | |
| assertEquals(listOf(Data(2), Data(2), Data(2)), atomic.compareAndExchange(cur, listOf(Data(3), Data(3), Data(3)))) | |
| assertEquals(listOf(Data(3), Data(3), Data(3)), atomic.compareAndExchange(cur, listOf(Data(4), Data(4), Data(4)))) | |
| assertEquals(listOf(Data(3), Data(3), Data(3)), atomic.compareAndExchange(cur, listOf(Data(3), Data(3), Data(3)))) | |
| } | |
| @Test | |
| fun compareAndSetComparingByReference() { | |
| val datum1 = Data(1) | |
| val datum2 = Data(1) | |
| val atomic = AtomicReference(datum1) | |
| assertEquals(datum1, datum2) | |
| assertNotSame(datum1, datum2) | |
| // datum1 is equal to itself, CAS should succeed | |
| assertTrue(atomic.compareAndSet(datum1, datum2)) | |
| // datum2 is not equal to datum1, they are two distinct, so CAS should fail | |
| assertFalse(atomic.compareAndSet(datum1, Data(2))) | |
| } | |
| @Test | |
| fun toStringTest() { | |
| assertEquals("Data(value=42)", AtomicReference(Data(42)).toString()) | |
| } | |
| @Test | |
| fun update() { | |
| val expected = Data(42) | |
| val a = AtomicReference(Data(0)) | |
| a.update { expected } | |
| assertSame(expected, a.load()) | |
| } | |
| @Test | |
| fun updateAndGet() { | |
| val expected = Data(42) | |
| val a = AtomicReference(Data(0)) | |
| assertSame(expected, a.updateAndFetch { expected }) | |
| assertSame(expected, a.load()) | |
| assertSame(expected, a.updateAndFetch { it }) | |
| assertSame(expected, a.load()) | |
| } | |
| @Test | |
| fun getAndUpdate() { | |
| val expected = Data(42) | |
| val old = Data(0) | |
| val a = AtomicReference(old) | |
| assertSame(old, a.fetchAndUpdate { expected }) | |
| assertSame(expected, a.load()) | |
| assertSame(expected, a.fetchAndUpdate { it }) | |
| assertSame(expected, a.load()) | |
| } | |
| } |