[stdlib] Introduced Common Atomic and Atomic Arrays.
JVM implementation is delegated to builtin classes.
diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/concurrent/AtomicArrays.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/concurrent/AtomicArrays.kt
deleted file mode 100644
index 793e43a..0000000
--- a/kotlin-native/runtime/src/main/kotlin/kotlin/concurrent/AtomicArrays.kt
+++ /dev/null
@@ -1,712 +0,0 @@
-/*
- * Copyright 2010-2023 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.
- */
-
-package kotlin.concurrent
-
-import kotlin.native.internal.*
-import kotlin.reflect.*
-import kotlin.concurrent.*
-import kotlin.native.concurrent.*
-import kotlin.internal.RequireKotlin
-import kotlin.internal.RequireKotlinVersionKind
-
-/**
- * An [IntArray] in which elements are always updated atomically.
- * For additional details about atomicity guarantees for reads and writes see [kotlin.concurrent.Volatile].
- */
-@SinceKotlin("1.9")
-@RequireKotlin(version = "1.9.20", versionKind = RequireKotlinVersionKind.COMPILER_VERSION)
-@ExperimentalStdlibApi
-public class AtomicIntArray {
- private val array: IntArray
-
- /**
- * Creates a new [AtomicIntArray] of the given [size], with all elements initialized to zero.
- *
- * @throws RuntimeException if the specified [size] is negative.
- */
- public constructor(size: Int) {
- array = IntArray(size)
- }
-
- /**
- * Creates a new [AtomicIntArray] filled with elements of the given [array].
- */
- @PublishedApi
- internal constructor(array: IntArray) {
- this.array = array.copyOf()
- }
-
- /**
- * Returns the number of elements in the array.
- */
- public val length: Int get() = array.size
-
- /**
- * Atomically gets the value of the element at the given [index].
- *
- * Provides sequential consistent ordering guarantees.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public operator fun get(index: Int): Int {
- checkBounds(index)
- return array.atomicGet(index)
- }
-
- /**
- * Atomically sets the value of the element at the given [index] to the [new value][newValue].
- *
- * Provides sequential consistent ordering guarantees.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public operator fun set(index: Int, newValue: Int): Unit {
- checkBounds(index)
- array.atomicSet(index, newValue)
- }
-
- /**
- * Atomically sets the value of the element at the given [index] to the [new value][newValue]
- * and returns the old value of the element.
- *
- * Provides sequential consistent ordering guarantees.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public fun getAndSet(index: Int, newValue: Int): Int {
- checkBounds(index)
- return array.getAndSet(index, newValue)
- }
-
- /**
- * Atomically sets the value of the element at the given [index] to the [new value][newValue]
- * if the current value equals the [expected value][expectedValue].
- * Returns true if the operation was successful and false only if the current value of the element was not equal to the expected value.
- *
- * Provides sequential consistent ordering guarantees and never fails spuriously.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public fun compareAndSet(index: Int, expectedValue: Int, newValue: Int): Boolean {
- checkBounds(index)
- return array.compareAndSet(index, expectedValue, newValue)
- }
-
- /**
- * Atomically sets the value of the element at the given [index] to the [new value][newValue]
- * if the current value equals the [expected value][expectedValue] and returns the old value of the element in any case.
- *
- * Provides sequential consistent ordering guarantees and never fails spuriously.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public fun compareAndExchange(index: Int, expectedValue: Int, newValue: Int): Int {
- checkBounds(index)
- return array.compareAndExchange(index, expectedValue, newValue)
- }
-
- /**
- * Atomically adds the given [delta] to the element at the given [index] and returns the old value of the element.
- *
- * Provides sequential consistent ordering guarantees.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public fun getAndAdd(index: Int, delta: Int): Int {
- checkBounds(index)
- return array.getAndAdd(index, delta)
- }
-
- /**
- * Atomically adds the given [delta] to the element at the given [index] and returns the new value of the element.
- *
- * Provides sequential consistent ordering guarantees.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public fun addAndGet(index: Int, delta: Int): Int {
- checkBounds(index)
- return array.getAndAdd(index, delta) + delta
- }
-
- /**
- * Atomically increments the element at the given [index] by one and returns the old value of the element.
- *
- * Provides sequential consistent ordering guarantees.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public fun getAndIncrement(index: Int): Int {
- checkBounds(index)
- return array.getAndAdd(index, 1)
- }
-
- /**
- * Atomically increments the element at the given [index] by one and returns the new value of the element.
- *
- * Provides sequential consistent ordering guarantees.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public fun incrementAndGet(index: Int): Int {
- checkBounds(index)
- return array.getAndAdd(index, 1) + 1
- }
-
- /**
- * Atomically decrements the element at the given [index] by one and returns the old value of the element.
- *
- * Provides sequential consistent ordering guarantees.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public fun getAndDecrement(index: Int): Int {
- checkBounds(index)
- return array.getAndAdd(index, -1)
- }
-
- /**
- * Atomically decrements the element at the given [index] by one and returns the new value of the element.
- *
- * Provides sequential consistent ordering guarantees.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public fun decrementAndGet(index: Int): Int {
- checkBounds(index)
- return array.getAndAdd(index, -1) - 1
- }
-
- /**
- * Returns the string representation of the underlying [IntArray][array].
- */
- public override fun toString(): String = array.toString()
-
- private fun checkBounds(index: Int) {
- if (index < 0 || index >= array.size) throw IndexOutOfBoundsException("The index $index is out of the bounds of the AtomicIntArray with size ${array.size}.")
- }
-}
-
-/**
- * Creates a new [AtomicIntArray] of the given [size], where each element is initialized by calling the given [init] function.
- *
- * The function [init] is called for each array element sequentially starting from the first one.
- * It should return the value for an array element given its index.
- *
- * @throws RuntimeException if the specified [size] is negative.
- */
-@SinceKotlin("1.9")
-@RequireKotlin(version = "1.9.20", versionKind = RequireKotlinVersionKind.COMPILER_VERSION)
-@ExperimentalStdlibApi
-public inline fun AtomicIntArray(size: Int, init: (Int) -> Int): AtomicIntArray {
- val inner = IntArray(size)
- for (index in 0 until size) {
- inner[index] = init(index)
- }
- return AtomicIntArray(inner)
-}
-
-/**
- * An [LongArray] in which elements are always updated atomically.
- * For additional details about atomicity guarantees for reads and writes see [kotlin.concurrent.Volatile].
- */
-@SinceKotlin("1.9")
-@RequireKotlin(version = "1.9.20", versionKind = RequireKotlinVersionKind.COMPILER_VERSION)
-@ExperimentalStdlibApi
-public class AtomicLongArray {
- private val array: LongArray
-
- /**
- * Creates a new [AtomicLongArray] of the given [size], with all elements initialized to zero.
- *
- * @throws RuntimeException if the specified [size] is negative.
- */
- public constructor(size: Int) {
- array = LongArray(size)
- }
-
- /**
- * Creates a new [AtomicLongArray] filled with elements of the given [array].
- */
- @PublishedApi
- internal constructor(array: LongArray) {
- this.array = array.copyOf()
- }
-
- /**
- * Returns the number of elements in the array.
- */
- public val length: Int get() = array.size
-
- /**
- * Atomically gets the value of the element at the given [index].
- *
- * Provides sequential consistent ordering guarantees.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public operator fun get(index: Int): Long {
- checkBounds(index)
- return array.atomicGet(index)
- }
-
- /**
- * Atomically sets the value of the element at the given [index] to the [new value][newValue].
- *
- * Provides sequential consistent ordering guarantees.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public operator fun set(index: Int, newValue: Long): Unit {
- checkBounds(index)
- array.atomicSet(index, newValue)
- }
-
- /**
- * Atomically sets the value of the element at the given [index] to the [new value][newValue]
- * and returns the old value of the element.
- *
- * Provides sequential consistent ordering guarantees.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public fun getAndSet(index: Int, newValue: Long): Long {
- checkBounds(index)
- return array.getAndSet(index, newValue)
- }
-
- /**
- * Atomically sets the value of the element at the given [index] to the [new value][newValue]
- * if the current value equals the [expected value][expectedValue].
- * Returns true if the operation was successful and false only if the current value of the element was not equal to the expected value.
- *
- * Provides sequential consistent ordering guarantees and never fails spuriously.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public fun compareAndSet(index: Int, expectedValue: Long, newValue: Long): Boolean {
- checkBounds(index)
- return array.compareAndSet(index, expectedValue, newValue)
- }
-
- /**
- * Atomically sets the value of the element at the given [index] to the [new value][newValue]
- * if the current value equals the [expected value][expectedValue] and returns the old value of the element in any case.
- *
- * Provides sequential consistent ordering guarantees and never fails spuriously.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public fun compareAndExchange(index: Int, expectedValue: Long, newValue: Long): Long {
- checkBounds(index)
- return array.compareAndExchange(index, expectedValue, newValue)
- }
-
- /**
- * Atomically adds the given [delta] to the element at the given [index] and returns the old value of the element.
- *
- * Provides sequential consistent ordering guarantees.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public fun getAndAdd(index: Int, delta: Long): Long {
- checkBounds(index)
- return array.getAndAdd(index, delta)
- }
-
- /**
- * Atomically adds the given [delta] to the element at the given [index] and returns the new value of the element.
- *
- * Provides sequential consistent ordering guarantees.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public fun addAndGet(index: Int, delta: Long): Long {
- checkBounds(index)
- return array.getAndAdd(index, delta) + delta
- }
-
- /**
- * Atomically increments the element at the given [index] by one and returns the old value of the element.
- *
- * Provides sequential consistent ordering guarantees.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public fun getAndIncrement(index: Int): Long {
- checkBounds(index)
- return array.getAndAdd(index, 1L)
- }
-
- /**
- * Atomically increments the element at the given [index] by one and returns the new value of the element.
- *
- * Provides sequential consistent ordering guarantees.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public fun incrementAndGet(index: Int): Long {
- checkBounds(index)
- return array.getAndAdd(index, 1L) + 1L
- }
-
- /**
- * Atomically decrements the element at the given [index] by one and returns the old value of the element.
- *
- * Provides sequential consistent ordering guarantees.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public fun getAndDecrement(index: Int): Long {
- checkBounds(index)
- return array.getAndAdd(index, -1L)
- }
-
- /**
- * Atomically decrements the element at the given [index] by one and returns the new value of the element.
- *
- * Provides sequential consistent ordering guarantees.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public fun decrementAndGet(index: Int): Long {
- checkBounds(index)
- return array.getAndAdd(index, -1L) - 1L
- }
-
- /**
- * Returns the string representation of the underlying [IntArray][array].
- */
- public override fun toString(): String = array.toString()
-
- private fun checkBounds(index: Int) {
- if (index < 0 || index >= array.size) throw IndexOutOfBoundsException("The index $index is out of the bounds of the AtomicLongArray with size ${array.size}.")
- }
-}
-
-/**
- * Creates a new [AtomicLongArray] of the given [size], where each element is initialized by calling the given [init] function.
- *
- * The function [init] is called for each array element sequentially starting from the first one.
- * It should return the value for an array element given its index.
- *
- * @throws RuntimeException if the specified [size] is negative.
- */
-@SinceKotlin("1.9")
-@RequireKotlin(version = "1.9.20", versionKind = RequireKotlinVersionKind.COMPILER_VERSION)
-@ExperimentalStdlibApi
-public inline fun AtomicLongArray(size: Int, init: (Int) -> Long): AtomicLongArray {
- val inner = LongArray(size)
- for (index in 0 until size) {
- inner[index] = init(index)
- }
- return AtomicLongArray(inner)
-}
-
-/**
- * An [Array]<T> in which elements are always updated atomically.
- * For additional details about atomicity guarantees for reads and writes see [kotlin.concurrent.Volatile].
- */
-@SinceKotlin("1.9")
-@RequireKotlin(version = "1.9.20", versionKind = RequireKotlinVersionKind.COMPILER_VERSION)
-@ExperimentalStdlibApi
-public class AtomicArray<T> {
- private val array: Array<T>
-
- /**
- * Creates a new [AtomicArray]<T> filled with elements of the given [array].
- */
- @PublishedApi
- internal constructor(array: Array<T>) {
- this.array = array.copyOf()
- }
-
- /**
- * Returns the number of elements in the array.
- */
- public val length: Int get() = array.size
-
- /**
- * Atomically gets the value of the element at the given [index].
- *
- * Provides sequential consistent ordering guarantees.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public operator fun get(index: Int): T {
- checkBounds(index)
- return array.atomicGet(index)
- }
-
- /**
- * Atomically sets the value of the element at the given [index] to the [new value][newValue].
- *
- * Provides sequential consistent ordering guarantees.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public operator fun set(index: Int, newValue: T): Unit {
- checkBounds(index)
- array.atomicSet(index, newValue)
- }
-
- /**
- * Atomically sets the value of the element at the given [index] to the [new value][newValue]
- * and returns the old value of the element.
- *
- * Provides sequential consistent ordering guarantees.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public fun getAndSet(index: Int, newValue: T): T {
- checkBounds(index)
- return array.getAndSet(index, newValue)
- }
-
- /**
- * Atomically sets the value of the element at the given [index] to the [new value][newValue]
- * if the current value equals the [expected value][expectedValue].
- * Returns true if the operation was successful and false only if the current value of the element was not equal to the expected value.
- *
- * Provides sequential consistent ordering guarantees and never fails spuriously.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public fun compareAndSet(index: Int, expectedValue: T, newValue: T): Boolean {
- checkBounds(index)
- return array.compareAndSet(index, expectedValue, newValue)
- }
-
- /**
- * Atomically sets the value of the element at the given [index] to the [new value][newValue]
- * if the current value equals the [expected value][expectedValue] and returns the old value of the element in any case.
- *
- * Provides sequential consistent ordering guarantees and never fails spuriously.
- *
- * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
- */
- public fun compareAndExchange(index: Int, expectedValue: T, newValue: T): T {
- checkBounds(index)
- return array.compareAndExchange(index, expectedValue, newValue)
- }
-
- /**
- * Returns the string representation of the underlying [IntArray][array].
- */
- public override fun toString(): String = array.toString()
-
- private fun checkBounds(index: Int) {
- if (index < 0 || index >= array.size) throw IndexOutOfBoundsException("The index $index is out of the bounds of the AtomicArray with size ${array.size}.")
- }
-}
-
-/**
- * Creates a new [AtomicArray]<T> of the given [size], where each element is initialized by calling the given [init] function.
- *
- * The function [init] is called for each array element sequentially starting from the first one.
- * It should return the value for an array element given its index.
- *
- * @throws RuntimeException if the specified [size] is negative.
- */
-@SinceKotlin("1.9")
-@RequireKotlin(version = "1.9.20", versionKind = RequireKotlinVersionKind.COMPILER_VERSION)
-@ExperimentalStdlibApi
-@Suppress("UNCHECKED_CAST")
-public inline fun <reified T> AtomicArray(size: Int, init: (Int) -> T): AtomicArray<T> {
- val inner = arrayOfNulls<T>(size)
- for (index in 0 until size) {
- inner[index] = init(index)
- }
- return AtomicArray(inner as Array<T>)
-}
-
-/**
- * Atomically gets the value of the [IntArray][this] element at the given [index].
- *
- * Provides sequential consistent ordering guarantees.
- *
- * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
- */
-@TypedIntrinsic(IntrinsicType.ATOMIC_GET_ARRAY_ELEMENT)
-internal external fun IntArray.atomicGet(index: Int): Int
-
-/**
- * Atomically sets the value of the [IntArray][this] element at the given [index] to the [new value][newValue].
- *
- * Provides sequential consistent ordering guarantees.
- *
- * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
- */
-@TypedIntrinsic(IntrinsicType.ATOMIC_SET_ARRAY_ELEMENT)
-internal external fun IntArray.atomicSet(index: Int, newValue: Int)
-
-/**
- * Atomically sets the value of the [IntArray][this] element at the given [index] to the [new value][newValue]
- * and returns the old value of the element.
- *
- * Provides sequential consistent ordering guarantees.
- *
- * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
- */
-@TypedIntrinsic(IntrinsicType.GET_AND_SET_ARRAY_ELEMENT)
-internal external fun IntArray.getAndSet(index: Int, newValue: Int): Int
-
-/**
- * Atomically adds the given [delta] to the [IntArray][this] element at the given [index]
- * and returns the old value of the element.
- *
- * Provides sequential consistent ordering guarantees.
- *
- * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
- */
-@TypedIntrinsic(IntrinsicType.GET_AND_ADD_ARRAY_ELEMENT)
-internal external fun IntArray.getAndAdd(index: Int, delta: Int): Int
-
-/**
- * Atomically sets the value of the [IntArray][this] element at the given [index] to the [new value][newValue]
- * if the current value equals the [expected value][expectedValue] and returns the old value of the element in any case.
- *
- * Provides sequential consistent ordering guarantees and never fails spuriously.
- *
- * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
- */
-@TypedIntrinsic(IntrinsicType.COMPARE_AND_EXCHANGE_ARRAY_ELEMENT)
-internal external fun IntArray.compareAndExchange(index: Int, expectedValue: Int, newValue: Int): Int
-
-/**
- * Atomically sets the value of the [IntArray][this] element at the given [index] to the [new value][newValue]
- * if the current value equals the [expected value][expectedValue].
- * Returns true if the operation was successful and false only if the current value of the element was not equal to the expected value.
- *
- * Provides sequential consistent ordering guarantees and never fails spuriously.
- *
- * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
- */
-@TypedIntrinsic(IntrinsicType.COMPARE_AND_SET_ARRAY_ELEMENT)
-internal external fun IntArray.compareAndSet(index: Int, expectedValue: Int, newValue: Int): Boolean
-
-/**
- * Atomically gets the value of the [LongArray][this] element at the given [index].
- *
- * Provides sequential consistent ordering guarantees.
- *
- * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
- */
-@TypedIntrinsic(IntrinsicType.ATOMIC_GET_ARRAY_ELEMENT)
-internal external fun LongArray.atomicGet(index: Int): Long
-
-/**
- * Atomically sets the value of the [LongArray][this] element at the given [index] to the [new value][newValue].
- *
- * Provides sequential consistent ordering guarantees.
- *
- * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
- */
-@TypedIntrinsic(IntrinsicType.ATOMIC_SET_ARRAY_ELEMENT)
-internal external fun LongArray.atomicSet(index: Int, newValue: Long)
-
-/**
- * Atomically sets the value of the [LongArray][this] element at the given [index] to the [new value][newValue]
- * and returns the old value of the element.
- *
- * Provides sequential consistent ordering guarantees.
- *
- * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
- */
-@TypedIntrinsic(IntrinsicType.GET_AND_SET_ARRAY_ELEMENT)
-internal external fun LongArray.getAndSet(index: Int, newValue: Long): Long
-
-/**
- * Atomically adds the given [delta] to the [LongArray][this] element at the given [index]
- * and returns the old value of the element.
- *
- * Provides sequential consistent ordering guarantees.
- *
- * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
- */
-@TypedIntrinsic(IntrinsicType.GET_AND_ADD_ARRAY_ELEMENT)
-internal external fun LongArray.getAndAdd(index: Int, delta: Long): Long
-
-/**
- * Atomically sets the value of the [LongArray][this] element at the given [index] to the [new value][newValue]
- * if the current value equals the [expected value][expectedValue] and returns the old value of the element in any case.
- *
- * Provides sequential consistent ordering guarantees and never fails spuriously.
- *
- * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
- */
-@TypedIntrinsic(IntrinsicType.COMPARE_AND_EXCHANGE_ARRAY_ELEMENT)
-internal external fun LongArray.compareAndExchange(index: Int, expectedValue: Long, newValue: Long): Long
-
-/**
- * Atomically sets the value of the [LongArray][this] element at the given [index] to the [new value][newValue]
- * if the current value equals the [expected value][expectedValue].
- * Returns true if the operation was successful and false only if the current value of the element was not equal to the expected value.
- *
- * Provides sequential consistent ordering guarantees and never fails spuriously.
- *
- * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
- */
-@TypedIntrinsic(IntrinsicType.COMPARE_AND_SET_ARRAY_ELEMENT)
-internal external fun LongArray.compareAndSet(index: Int, expectedValue: Long, newValue: Long): Boolean
-
-/**
- * Atomically gets the value of the [Array<T>][this] element at the given [index].
- *
- * Provides sequential consistent ordering guarantees.
- *
- * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
- */
-@TypedIntrinsic(IntrinsicType.ATOMIC_GET_ARRAY_ELEMENT)
-internal external fun <T> Array<T>.atomicGet(index: Int): T
-
-/**
- * Atomically sets the value of the [Array<T>][this] element at the given [index] to the [new value][newValue].
- *
- * Provides sequential consistent ordering guarantees.
- *
- * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
- */
-@TypedIntrinsic(IntrinsicType.ATOMIC_SET_ARRAY_ELEMENT)
-internal external fun <T> Array<T>.atomicSet(index: Int, newValue: T)
-
-/**
- * Atomically sets the value of the [Array<T>][this] element at the given [index] to the [new value][newValue]
- * and returns the old value of the element.
- *
- * Provides sequential consistent ordering guarantees.
- *
- * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
- */
-@TypedIntrinsic(IntrinsicType.GET_AND_SET_ARRAY_ELEMENT)
-internal external fun <T> Array<T>.getAndSet(index: Int, value: T): T
-
-/**
- * Atomically sets the value of the [Array<T>][this] element at the given [index] to the [new value][newValue]
- * if the current value equals the [expected value][expectedValue] and returns the old value of the element in any case.
- *
- * Comparison of values is done by reference.
- *
- * Provides sequential consistent ordering guarantees and never fails spuriously.
- *
- * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
- */
-@TypedIntrinsic(IntrinsicType.COMPARE_AND_EXCHANGE_ARRAY_ELEMENT)
-internal external fun <T> Array<T>.compareAndExchange(index: Int, expectedValue: T, newValue: T): T
-
-/**
- * Atomically sets the value of the [Array<T>][this] element at the given [index] to the [new value][newValue]
- * if the current value equals the [expected value][expectedValue].
- * Returns true if the operation was successful and false only if the current value of the element was not equal to the expected value.
- *
- * Comparison of values is done by reference.
- *
- * Provides sequential consistent ordering guarantees and never fails spuriously.
- *
- * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
- */
-@TypedIntrinsic(IntrinsicType.COMPARE_AND_SET_ARRAY_ELEMENT)
-internal external fun <T> Array<T>.compareAndSet(index: Int, expectedValue: T, newValue: T): Boolean
diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/concurrent/AtomicArrays.native.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/concurrent/AtomicArrays.native.kt
new file mode 100644
index 0000000..57f4e80
--- /dev/null
+++ b/kotlin-native/runtime/src/main/kotlin/kotlin/concurrent/AtomicArrays.native.kt
@@ -0,0 +1,1067 @@
+/*
+ * Copyright 2010-2023 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.
+ */
+
+package kotlin.concurrent
+
+import kotlin.native.internal.*
+import kotlin.reflect.*
+import kotlin.concurrent.*
+import kotlin.native.concurrent.*
+import kotlin.internal.RequireKotlin
+import kotlin.internal.RequireKotlinVersionKind
+
+/**
+ * An array of ints in which elements may be updated atomically with guaranteed sequential consistent ordering.
+ *
+ * For additional details about atomicity guarantees for reads and writes see [kotlin.concurrent.Volatile].
+ */
+@SinceKotlin("1.9")
+@RequireKotlin(version = "1.9.20", versionKind = RequireKotlinVersionKind.COMPILER_VERSION)
+@ExperimentalStdlibApi
+public actual class AtomicIntArray {
+ private val array: IntArray
+
+ /**
+ * Creates a new [AtomicIntArray] of the given [size], with all elements initialized to zero.
+ *
+ * @throws RuntimeException if the specified [size] is negative.
+ */
+ public actual constructor(size: Int) {
+ array = IntArray(size)
+ }
+
+ /**
+ * Creates a new [AtomicIntArray] filled with elements of the given [array].
+ */
+ public actual constructor(array: IntArray) {
+ this.array = array.copyOf()
+ }
+
+ /**
+ * Returns the number of elements in the array.
+ */
+ public actual val size: Int get() = array.size
+
+ /**
+ * Returns the number of elements in the array.
+ */
+ @Deprecated("Use size instead.", ReplaceWith("this.size"))
+ public val length: Int get() = array.size
+
+ /**
+ * Atomically gets the value of the element at the given [index].
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun loadAt(index: Int): Int {
+ checkBounds(index)
+ return array.atomicGet(index)
+ }
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue].
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun storeAt(index: Int, newValue: Int): Unit {
+ checkBounds(index)
+ array.atomicSet(index, newValue)
+ }
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun exchangeAt(index: Int, newValue: Int): Int {
+ checkBounds(index)
+ return array.getAndSet(index, newValue)
+ }
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue].
+ * Returns true if the operation was successful and false only if the current value of the element was not equal to the expected value.
+ *
+ * Provides sequential consistent ordering guarantees and never fails spuriously.
+ *
+ * Comparison of values is done by value.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun compareAndSetAt(index: Int, expectedValue: Int, newValue: Int): Boolean {
+ checkBounds(index)
+ return array.compareAndSet(index, expectedValue, newValue)
+ }
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue] and returns the old value of the element in any case.
+ *
+ * Provides sequential consistent ordering guarantees and never fails spuriously.
+ *
+ * Comparison of values is done by value.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun compareAndExchangeAt(index: Int, expectedValue: Int, newValue: Int): Int {
+ checkBounds(index)
+ return array.compareAndExchange(index, expectedValue, newValue)
+ }
+
+ /**
+ * Atomically adds the given [delta] to the element at the given [index] and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun fetchAndAddAt(index: Int, delta: Int): Int {
+ checkBounds(index)
+ return array.getAndAdd(index, delta)
+ }
+
+ /**
+ * Atomically adds the given [delta] to the element at the given [index] and returns the new value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun addAndFetchAt(index: Int, delta: Int): Int {
+ checkBounds(index)
+ return array.getAndAdd(index, delta) + delta
+ }
+
+ /**
+ * Atomically increments the element at the given [index] by one and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun fetchAndIncrementAt(index: Int): Int {
+ checkBounds(index)
+ return array.getAndAdd(index, 1)
+ }
+
+ /**
+ * Atomically increments the element at the given [index] by one and returns the new value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun incrementAndFetchAt(index: Int): Int {
+ checkBounds(index)
+ return array.getAndAdd(index, 1) + 1
+ }
+
+ /**
+ * Atomically decrements the element at the given [index] by one and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun fetchAndDecrementAt(index: Int): Int {
+ checkBounds(index)
+ return array.getAndAdd(index, -1)
+ }
+
+ /**
+ * Atomically decrements the element at the given [index] by one and returns the new value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun decrementAndFetchAt(index: Int): Int {
+ checkBounds(index)
+ return array.getAndAdd(index, -1) - 1
+ }
+
+ /**
+ * Atomically gets the value of the element at the given [index].
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use loadAt(index: Int) instead.", ReplaceWith("this.loadAt(index)"))
+ public operator fun get(index: Int): Int {
+ checkBounds(index)
+ return array.atomicGet(index)
+ }
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue].
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use storeAt(index: Int, newValue: Int) instead.", ReplaceWith("this.storeAt(index, newValue)"))
+ public operator fun set(index: Int, newValue: Int): Unit {
+ checkBounds(index)
+ array.atomicSet(index, newValue)
+ }
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use exchangeAt(index: Int, newValue: Int) instead.", ReplaceWith("this.exchangeAt(index, newValue)"))
+ public fun getAndSet(index: Int, newValue: Int): Int {
+ checkBounds(index)
+ return array.getAndSet(index, newValue)
+ }
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue].
+ * Returns true if the operation was successful and false only if the current value of the element was not equal to the expected value.
+ *
+ * Provides sequential consistent ordering guarantees and never fails spuriously.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use compareAndSetAt(index: Int, expectedValue: Int, newValue: Int) instead.", ReplaceWith("this.compareAndSetAt(index, expectedValue, newValue)"))
+ public fun compareAndSet(index: Int, expectedValue: Int, newValue: Int): Boolean {
+ checkBounds(index)
+ return array.compareAndSet(index, expectedValue, newValue)
+ }
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue] and returns the old value of the element in any case.
+ *
+ * Provides sequential consistent ordering guarantees and never fails spuriously.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use compareAndExchangeAt(index: Int, expectedValue: Int, newValue: Int) instead.", ReplaceWith("this.compareAndExchangeAt(index, expectedValue, newValue)"))
+ public fun compareAndExchange(index: Int, expectedValue: Int, newValue: Int): Int {
+ checkBounds(index)
+ return array.compareAndExchange(index, expectedValue, newValue)
+ }
+
+ /**
+ * Atomically adds the given [delta] to the element at the given [index] and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use fetchAndAddAt(index: Int, delta: Int) instead.", ReplaceWith("this.fetchAndAddAt(index, delta)"))
+ public fun getAndAdd(index: Int, delta: Int): Int {
+ checkBounds(index)
+ return array.getAndAdd(index, delta)
+ }
+
+ /**
+ * Atomically adds the given [delta] to the element at the given [index] and returns the new value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use addAndFetchAt(index: Int, delta: Int) instead.", ReplaceWith("this.addAndFetchAt(index, delta)"))
+ public fun addAndGet(index: Int, delta: Int): Int {
+ checkBounds(index)
+ return array.getAndAdd(index, delta) + delta
+ }
+
+ /**
+ * Atomically increments the element at the given [index] by one and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use fetchAndIncrementAt(index: Int) instead.", ReplaceWith("this.fetchAndIncrementAt(index)"))
+ public fun getAndIncrement(index: Int): Int {
+ checkBounds(index)
+ return array.getAndAdd(index, 1)
+ }
+
+ /**
+ * Atomically increments the element at the given [index] by one and returns the new value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use incrementAndFetchAt(index: Int) instead.", ReplaceWith("this.incrementAndFetchAt(index)"))
+ public fun incrementAndGet(index: Int): Int {
+ checkBounds(index)
+ return array.getAndAdd(index, 1) + 1
+ }
+
+ /**
+ * Atomically decrements the element at the given [index] by one and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use fetchAndDecrementAt(index: Int) instead.", ReplaceWith("this.fetchAndDecrementAt(index)"))
+ public fun getAndDecrement(index: Int): Int {
+ checkBounds(index)
+ return array.getAndAdd(index, -1)
+ }
+
+ /**
+ * Atomically decrements the element at the given [index] by one and returns the new value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use decrementAndFetchAt(index: Int) instead.", ReplaceWith("this.decrementAndFetchAt(index)"))
+ public fun decrementAndGet(index: Int): Int {
+ checkBounds(index)
+ return array.getAndAdd(index, -1) - 1
+ }
+
+ /**
+ * Returns the string representation of the underlying array of ints.
+ *
+ * This operation does not provide any atomicity guarantees.
+ */
+ public actual override fun toString(): String = array.toString()
+
+ // See KT-71459
+ private fun checkBounds(index: Int) {
+ if (index < 0 || index >= array.size) checkBoundsSlowPath(index)
+ }
+
+ private fun checkBoundsSlowPath(index: Int) {
+ throw IndexOutOfBoundsException("The index $index is out of the bounds of the AtomicIntArray with size ${array.size}.")
+ }
+}
+
+/**
+ * An array of longs in which elements may be updated atomically with guaranteed sequential consistent ordering.
+ *
+ * For additional details about atomicity guarantees for reads and writes see [kotlin.concurrent.Volatile].
+ */
+@SinceKotlin("1.9")
+@RequireKotlin(version = "1.9.20", versionKind = RequireKotlinVersionKind.COMPILER_VERSION)
+@ExperimentalStdlibApi
+public actual class AtomicLongArray {
+ private val array: LongArray
+
+ /**
+ * Creates a new [AtomicLongArray] of the specified [size], with all elements initialized to zero.
+ * @throws RuntimeException if the specified [size] is negative.
+ */
+ public actual constructor(size: Int) {
+ array = LongArray(size)
+ }
+
+ /**
+ * Creates a new [AtomicLongArray] filled with elements of the given [array].
+ */
+ public actual constructor(array: LongArray) {
+ this.array = array.copyOf()
+ }
+
+ /**
+ * Returns the number of elements in the array.
+ */
+ public actual val size: Int get() = array.size
+
+ /**
+ * Atomically gets the value of the element at the given [index].
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun loadAt(index: Int): Long {
+ checkBounds(index)
+ return array.atomicGet(index)
+ }
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue].
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun storeAt(index: Int, newValue: Long): Unit {
+ checkBounds(index)
+ array.atomicSet(index, newValue)
+ }
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun exchangeAt(index: Int, newValue: Long): Long {
+ checkBounds(index)
+ return array.getAndSet(index, newValue)
+ }
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue].
+ * Returns true if the operation was successful and false only if the current value of the element was not equal to the expected value.
+ *
+ * Provides sequential consistent ordering guarantees and never fails spuriously.
+ *
+ * Comparison of values is done by value.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun compareAndSetAt(index: Int, expectedValue: Long, newValue: Long): Boolean {
+ checkBounds(index)
+ return array.compareAndSet(index, expectedValue, newValue)
+ }
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue] and returns the old value of the element in any case.
+ *
+ * Provides sequential consistent ordering guarantees and never fails spuriously.
+ *
+ * Comparison of values is done by value.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun compareAndExchangeAt(index: Int, expectedValue: Long, newValue: Long): Long {
+ checkBounds(index)
+ return array.compareAndExchange(index, expectedValue, newValue)
+ }
+
+ /**
+ * Atomically adds the given [delta] to the element at the given [index] and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun fetchAndAddAt(index: Int, delta: Long): Long {
+ checkBounds(index)
+ return array.getAndAdd(index, delta)
+ }
+
+ /**
+ * Atomically adds the given [delta] to the element at the given [index] and returns the new value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun addAndFetchAt(index: Int, delta: Long): Long {
+ checkBounds(index)
+ return array.getAndAdd(index, delta) + delta
+ }
+
+ /**
+ * Atomically increments the element at the given [index] by one and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun fetchAndIncrementAt(index: Int): Long {
+ checkBounds(index)
+ return array.getAndAdd(index, 1)
+ }
+
+ /**
+ * Atomically increments the element at the given [index] by one and returns the new value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun incrementAndFetchAt(index: Int): Long {
+ checkBounds(index)
+ return array.getAndAdd(index, 1) + 1
+ }
+
+ /**
+ * Atomically decrements the element at the given [index] by one and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun fetchAndDecrementAt(index: Int): Long {
+ checkBounds(index)
+ return array.getAndAdd(index, -1)
+ }
+
+ /**
+ * Atomically decrements the element at the given [index] by one and returns the new value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun decrementAndFetchAt(index: Int): Long {
+ checkBounds(index)
+ return array.getAndAdd(index, -1) - 1
+ }
+
+ /**
+ * Returns the number of elements in the array.
+ */
+ @Deprecated("Use size instead.", ReplaceWith("this.size"))
+ public val length: Int get() = array.size
+
+ /**
+ * Atomically gets the value of the element at the given [index].
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use loadAt(index: Int) instead.", ReplaceWith("this.loadAt(index)"))
+ public operator fun get(index: Int): Long {
+ checkBounds(index)
+ return array.atomicGet(index)
+ }
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue].
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use storeAt(index: Int, newValue: Long) instead.", ReplaceWith("this.storeAt(index, newValue)"))
+ public operator fun set(index: Int, newValue: Long): Unit {
+ checkBounds(index)
+ array.atomicSet(index, newValue)
+ }
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use exchangeAt(index: Int, newValue: Long) instead.", ReplaceWith("this.exchangeAt(index, newValue)"))
+ public fun getAndSet(index: Int, newValue: Long): Long {
+ checkBounds(index)
+ return array.getAndSet(index, newValue)
+ }
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue].
+ * Returns true if the operation was successful and false only if the current value of the element was not equal to the expected value.
+ *
+ * Provides sequential consistent ordering guarantees and never fails spuriously.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use compareAndSetAt(index: Int, expectedValue: Long, newValue: Long) instead.", ReplaceWith("this.compareAndSetAt(index, expectedValue, newValue)"))
+ public fun compareAndSet(index: Int, expectedValue: Long, newValue: Long): Boolean {
+ checkBounds(index)
+ return array.compareAndSet(index, expectedValue, newValue)
+ }
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue] and returns the old value of the element in any case.
+ *
+ * Provides sequential consistent ordering guarantees and never fails spuriously.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use compareAndExchangeAt(index: Int, expectedValue: Long, newValue: Long) instead.", ReplaceWith("this.compareAndExchangeAt(index, expectedValue, newValue)"))
+ public fun compareAndExchange(index: Int, expectedValue: Long, newValue: Long): Long {
+ checkBounds(index)
+ return array.compareAndExchange(index, expectedValue, newValue)
+ }
+
+ /**
+ * Atomically adds the given [delta] to the element at the given [index] and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use fetchAndAddAt(index: Int, delta: Long) instead.", ReplaceWith("this.fetchAndAddAt(index, delta)"))
+ public fun getAndAdd(index: Int, delta: Long): Long {
+ checkBounds(index)
+ return array.getAndAdd(index, delta)
+ }
+
+ /**
+ * Atomically adds the given [delta] to the element at the given [index] and returns the new value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use addAndFetchAt(index: Int, delta: Long) instead.", ReplaceWith("this.addAndFetchAt(index, delta)"))
+ public fun addAndGet(index: Int, delta: Long): Long {
+ checkBounds(index)
+ return array.getAndAdd(index, delta) + delta
+ }
+
+ /**
+ * Atomically increments the element at the given [index] by one and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use fetchAndIncrementAt(index: Int) instead.", ReplaceWith("this.fetchAndIncrementAt(index)"))
+ public fun getAndIncrement(index: Int): Long {
+ checkBounds(index)
+ return array.getAndAdd(index, 1L)
+ }
+
+ /**
+ * Atomically increments the element at the given [index] by one and returns the new value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use incrementAndFetchAt(index: Int) instead.", ReplaceWith("this.incrementAndFetchAt(index)"))
+ public fun incrementAndGet(index: Int): Long {
+ checkBounds(index)
+ return array.getAndAdd(index, 1L) + 1L
+ }
+
+ /**
+ * Atomically decrements the element at the given [index] by one and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use fetchAndDecrementAt(index: Int) instead.", ReplaceWith("this.fetchAndDecrementAt(index)"))
+ public fun getAndDecrement(index: Int): Long {
+ checkBounds(index)
+ return array.getAndAdd(index, -1L)
+ }
+
+ /**
+ * Atomically decrements the element at the given [index] by one and returns the new value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use decrementAndFetchAt(index: Int) instead.", ReplaceWith("this.decrementAndFetchAt(index)"))
+ public fun decrementAndGet(index: Int): Long {
+ checkBounds(index)
+ return array.getAndAdd(index, -1L) - 1L
+ }
+
+ /**
+ * Returns the string representation of the underlying array of ints.
+ *
+ * This operation does not provide any atomicity guarantees.
+ */
+ public actual override fun toString(): String = array.toString()
+
+ // See KT-71459
+ private fun checkBounds(index: Int) {
+ if (index < 0 || index >= array.size) checkBoundsSlowPath(index)
+ }
+
+ private fun checkBoundsSlowPath(index: Int) {
+ throw IndexOutOfBoundsException("The index $index is out of the bounds of the AtomicIntArray with size ${array.size}.")
+ }
+}
+
+/**
+ * A generic array of objects in which elements may be updated atomically with guaranteed sequential consistent ordering.
+ *
+ * For additional details about atomicity guarantees for reads and writes see [kotlin.concurrent.Volatile].
+ */
+@SinceKotlin("1.9")
+@RequireKotlin(version = "1.9.20", versionKind = RequireKotlinVersionKind.COMPILER_VERSION)
+@ExperimentalStdlibApi
+public actual class AtomicArray<T> {
+ private val array: Array<T>
+
+ /**
+ * Creates a new [AtomicArray]<T> filled with elements of the given [array].
+ */
+ public actual constructor(array: Array<T>) {
+ this.array = array.copyOf()
+ }
+
+ /**
+ * Returns the number of elements in the array.
+ */
+ public actual val size: Int get() = array.size
+
+ /**
+ * Atomically gets the value of the element at the given [index].
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun loadAt(index: Int): T {
+ checkBounds(index)
+ return array.atomicGet(index)
+ }
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue].
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun storeAt(index: Int, newValue: T): Unit {
+ checkBounds(index)
+ array.atomicSet(index, newValue)
+ }
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun exchangeAt(index: Int, newValue: T): T {
+ checkBounds(index)
+ return array.getAndSet(index, newValue)
+ }
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue].
+ * Returns true if the operation was successful and false only if the current value of the element was not equal to the expected value.
+ *
+ * Provides sequential consistent ordering guarantees and never fails spuriously.
+ *
+ * Comparison of values is done by reference.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun compareAndSetAt(index: Int, expectedValue: T, newValue: T): Boolean {
+ checkBounds(index)
+ return array.compareAndSet(index, expectedValue, newValue)
+ }
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue] and returns the old value of the element in any case.
+ *
+ * Provides sequential consistent ordering guarantees and never fails spuriously.
+ *
+ * Comparison of values is done by reference.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun compareAndExchangeAt(index: Int, expectedValue: T, newValue: T): T {
+ checkBounds(index)
+ return array.compareAndExchange(index, expectedValue, newValue)
+ }
+
+ /**
+ * Returns the number of elements in the array.
+ */
+ @Deprecated("Use size instead.", ReplaceWith("this.size"))
+ public val length: Int get() = array.size
+
+ /**
+ * Atomically gets the value of the element at the given [index].
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use loadAt(index: Int) instead.", ReplaceWith("this.loadAt(index)"))
+ public operator fun get(index: Int): T {
+ checkBounds(index)
+ return array.atomicGet(index)
+ }
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue].
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use storeAt(index: Int, newValue: T) instead.", ReplaceWith("this.storeAt(index, newValue)"))
+ public operator fun set(index: Int, newValue: T): Unit {
+ checkBounds(index)
+ array.atomicSet(index, newValue)
+ }
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use exchangeAt(index: Int, newValue: T) instead.", ReplaceWith("this.exchangeAt(index, newValue)"))
+ public fun getAndSet(index: Int, newValue: T): T {
+ checkBounds(index)
+ return array.getAndSet(index, newValue)
+ }
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue].
+ * Returns true if the operation was successful and false only if the current value of the element was not equal to the expected value.
+ *
+ * Provides sequential consistent ordering guarantees and never fails spuriously.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use compareAndSetAt(index: Int, expectedValue: T, newValue: T) instead.", ReplaceWith("this.compareAndSetAt(index, expectedValue, newValue)"))
+ public fun compareAndSet(index: Int, expectedValue: T, newValue: T): Boolean {
+ checkBounds(index)
+ return array.compareAndSet(index, expectedValue, newValue)
+ }
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue] and returns the old value of the element in any case.
+ *
+ * Provides sequential consistent ordering guarantees and never fails spuriously.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ @Deprecated("Use compareAndExchangeAt(index: Int, expectedValue: T, newValue: T) instead.", ReplaceWith("this.compareAndExchangeAt(index, expectedValue, newValue)"))
+ public fun compareAndExchange(index: Int, expectedValue: T, newValue: T): T {
+ checkBounds(index)
+ return array.compareAndExchange(index, expectedValue, newValue)
+ }
+
+ /**
+ * Returns the string representation of the underlying array of objects.
+ *
+ * This operation does not provide any atomicity guarantees.
+ */
+ public actual override fun toString(): String = array.toString()
+
+ // See KT-71459
+ private fun checkBounds(index: Int) {
+ if (index < 0 || index >= array.size) checkBoundsSlowPath(index)
+ }
+
+ private fun checkBoundsSlowPath(index: Int) {
+ throw IndexOutOfBoundsException("The index $index is out of the bounds of the AtomicIntArray with size ${array.size}.")
+ }
+}
+
+/**
+ * Atomically gets the value of the [IntArray][this] element at the given [index].
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
+ */
+@TypedIntrinsic(IntrinsicType.ATOMIC_GET_ARRAY_ELEMENT)
+internal external fun IntArray.atomicGet(index: Int): Int
+
+/**
+ * Atomically sets the value of the [IntArray][this] element at the given [index] to the [new value][newValue].
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
+ */
+@TypedIntrinsic(IntrinsicType.ATOMIC_SET_ARRAY_ELEMENT)
+internal external fun IntArray.atomicSet(index: Int, newValue: Int)
+
+/**
+ * Atomically sets the value of the [IntArray][this] element at the given [index] to the [new value][newValue]
+ * and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
+ */
+@TypedIntrinsic(IntrinsicType.GET_AND_SET_ARRAY_ELEMENT)
+internal external fun IntArray.getAndSet(index: Int, newValue: Int): Int
+
+/**
+ * Atomically adds the given [delta] to the [IntArray][this] element at the given [index]
+ * and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
+ */
+@TypedIntrinsic(IntrinsicType.GET_AND_ADD_ARRAY_ELEMENT)
+internal external fun IntArray.getAndAdd(index: Int, delta: Int): Int
+
+/**
+ * Atomically sets the value of the [IntArray][this] element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue] and returns the old value of the element in any case.
+ *
+ * Provides sequential consistent ordering guarantees and never fails spuriously.
+ *
+ * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
+ */
+@TypedIntrinsic(IntrinsicType.COMPARE_AND_EXCHANGE_ARRAY_ELEMENT)
+internal external fun IntArray.compareAndExchange(index: Int, expectedValue: Int, newValue: Int): Int
+
+/**
+ * Atomically sets the value of the [IntArray][this] element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue].
+ * Returns true if the operation was successful and false only if the current value of the element was not equal to the expected value.
+ *
+ * Provides sequential consistent ordering guarantees and never fails spuriously.
+ *
+ * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
+ */
+@TypedIntrinsic(IntrinsicType.COMPARE_AND_SET_ARRAY_ELEMENT)
+internal external fun IntArray.compareAndSet(index: Int, expectedValue: Int, newValue: Int): Boolean
+
+/**
+ * Atomically gets the value of the [LongArray][this] element at the given [index].
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
+ */
+@TypedIntrinsic(IntrinsicType.ATOMIC_GET_ARRAY_ELEMENT)
+internal external fun LongArray.atomicGet(index: Int): Long
+
+/**
+ * Atomically sets the value of the [LongArray][this] element at the given [index] to the [new value][newValue].
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
+ */
+@TypedIntrinsic(IntrinsicType.ATOMIC_SET_ARRAY_ELEMENT)
+internal external fun LongArray.atomicSet(index: Int, newValue: Long)
+
+/**
+ * Atomically sets the value of the [LongArray][this] element at the given [index] to the [new value][newValue]
+ * and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
+ */
+@TypedIntrinsic(IntrinsicType.GET_AND_SET_ARRAY_ELEMENT)
+internal external fun LongArray.getAndSet(index: Int, newValue: Long): Long
+
+/**
+ * Atomically adds the given [delta] to the [LongArray][this] element at the given [index]
+ * and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
+ */
+@TypedIntrinsic(IntrinsicType.GET_AND_ADD_ARRAY_ELEMENT)
+internal external fun LongArray.getAndAdd(index: Int, delta: Long): Long
+
+/**
+ * Atomically sets the value of the [LongArray][this] element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue] and returns the old value of the element in any case.
+ *
+ * Provides sequential consistent ordering guarantees and never fails spuriously.
+ *
+ * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
+ */
+@TypedIntrinsic(IntrinsicType.COMPARE_AND_EXCHANGE_ARRAY_ELEMENT)
+internal external fun LongArray.compareAndExchange(index: Int, expectedValue: Long, newValue: Long): Long
+
+/**
+ * Atomically sets the value of the [LongArray][this] element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue].
+ * Returns true if the operation was successful and false only if the current value of the element was not equal to the expected value.
+ *
+ * Provides sequential consistent ordering guarantees and never fails spuriously.
+ *
+ * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
+ */
+@TypedIntrinsic(IntrinsicType.COMPARE_AND_SET_ARRAY_ELEMENT)
+internal external fun LongArray.compareAndSet(index: Int, expectedValue: Long, newValue: Long): Boolean
+
+/**
+ * Atomically gets the value of the [Array<T>][this] element at the given [index].
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
+ */
+@TypedIntrinsic(IntrinsicType.ATOMIC_GET_ARRAY_ELEMENT)
+internal external fun <T> Array<T>.atomicGet(index: Int): T
+
+/**
+ * Atomically sets the value of the [Array<T>][this] element at the given [index] to the [new value][newValue].
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
+ */
+@TypedIntrinsic(IntrinsicType.ATOMIC_SET_ARRAY_ELEMENT)
+internal external fun <T> Array<T>.atomicSet(index: Int, newValue: T)
+
+/**
+ * Atomically sets the value of the [Array<T>][this] element at the given [index] to the [new value][newValue]
+ * and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
+ */
+@TypedIntrinsic(IntrinsicType.GET_AND_SET_ARRAY_ELEMENT)
+internal external fun <T> Array<T>.getAndSet(index: Int, value: T): T
+
+/**
+ * Atomically sets the value of the [Array<T>][this] element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue] and returns the old value of the element in any case.
+ *
+ * Comparison of values is done by reference.
+ *
+ * Provides sequential consistent ordering guarantees and never fails spuriously.
+ *
+ * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
+ */
+@TypedIntrinsic(IntrinsicType.COMPARE_AND_EXCHANGE_ARRAY_ELEMENT)
+internal external fun <T> Array<T>.compareAndExchange(index: Int, expectedValue: T, newValue: T): T
+
+/**
+ * Atomically sets the value of the [Array<T>][this] element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue].
+ * Returns true if the operation was successful and false only if the current value of the element was not equal to the expected value.
+ *
+ * Comparison of values is done by reference.
+ *
+ * Provides sequential consistent ordering guarantees and never fails spuriously.
+ *
+ * NOTE: Ensure that the provided [index] does not exceed the size of the [array][this]. Exceeding the array size may result in undefined behavior.
+ */
+@TypedIntrinsic(IntrinsicType.COMPARE_AND_SET_ARRAY_ELEMENT)
+internal external fun <T> Array<T>.compareAndSet(index: Int, expectedValue: T, newValue: T): Boolean
diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/concurrent/Atomics.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/concurrent/Atomics.kt
deleted file mode 100644
index ca5de3e..0000000
--- a/kotlin-native/runtime/src/main/kotlin/kotlin/concurrent/Atomics.kt
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * Copyright 2010-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
- * that can be found in the LICENSE file.
- */
-
-package kotlin.concurrent
-
-import kotlinx.cinterop.NativePtr
-import kotlinx.cinterop.ExperimentalForeignApi
-import kotlin.native.internal.*
-import kotlin.reflect.*
-import kotlin.concurrent.*
-import kotlin.native.concurrent.*
-
-/**
- * An [Int] value that is always updated atomically.
- * For additional details about atomicity guarantees for reads and writes see [kotlin.concurrent.Volatile].
- */
-@SinceKotlin("1.9")
-public class AtomicInt(@Volatile public var value: Int) {
- /**
- * Atomically sets the value to the given [new value][newValue] and returns the old value.
- */
- public fun getAndSet(newValue: Int): Int = this::value.getAndSetField(newValue)
-
- /**
- * Atomically sets the value to the given [new value][newValue] if the current value equals the [expected value][expected],
- * returns true if the operation was successful and false only if the current value was not equal to the expected value.
- *
- * Provides sequential consistent ordering guarantees and cannot fail spuriously.
- */
- public fun compareAndSet(expected: Int, newValue: Int): Boolean = this::value.compareAndSetField(expected, newValue)
-
- /**
- * Atomically sets the value to the given [new value][newValue] if the current value equals the [expected value][expected]
- * and returns the old value in any case.
- *
- * Provides sequential consistent ordering guarantees and cannot fail spuriously.
- */
- public fun compareAndExchange(expected: Int, newValue: Int): Int = this::value.compareAndExchangeField(expected, newValue)
-
- /**
- * Atomically adds the [given value][delta] to the current value and returns the old value.
- */
- public fun getAndAdd(delta: Int): Int = this::value.getAndAddField(delta)
-
- /**
- * Atomically adds the [given value][delta] to the current value and returns the new value.
- */
- public fun addAndGet(delta: Int): Int = this::value.getAndAddField(delta) + delta
-
- /**
- * Atomically increments the current value by one and returns the old value.
- */
- public fun getAndIncrement(): Int = this::value.getAndAddField(1)
-
- /**
- * Atomically increments the current value by one and returns the new value.
- */
- public fun incrementAndGet(): Int = this::value.getAndAddField(1) + 1
-
- /**
- * Atomically decrements the current value by one and returns the new value.
- */
- public fun decrementAndGet(): Int = this::value.getAndAddField(-1) - 1
-
- /**
- * Atomically decrements the current value by one and returns the old value.
- */
- public fun getAndDecrement(): Int = this::value.getAndAddField(-1)
-
- /**
- * Returns the string representation of the current [value].
- */
- public override fun toString(): String = value.toString()
-}
-
-/**
- * A [Long] value that is always updated atomically.
- * For additional details about atomicity guarantees for reads and writes see [kotlin.concurrent.Volatile].
- *
- */
-@SinceKotlin("1.9")
-public class AtomicLong(@Volatile public var value: Long) {
- /**
- * Atomically sets the value to the given [new value][newValue] and returns the old value.
- */
- public fun getAndSet(newValue: Long): Long = this::value.getAndSetField(newValue)
-
- /**
- * Atomically sets the value to the given [new value][newValue] if the current value equals the [expected value][expected],
- * returns true if the operation was successful and false only if the current value was not equal to the expected value.
- *
- * Provides sequential consistent ordering guarantees and cannot fail spuriously.
- */
- public fun compareAndSet(expected: Long, newValue: Long): Boolean = this::value.compareAndSetField(expected, newValue)
-
- /**
- * Atomically sets the value to the given [new value][newValue] if the current value equals the [expected value][expected]
- * and returns the old value in any case.
- *
- * Provides sequential consistent ordering guarantees and cannot fail spuriously.
- */
- public fun compareAndExchange(expected: Long, newValue: Long): Long = this::value.compareAndExchangeField(expected, newValue)
-
- /**
- * Atomically adds the [given value][delta] to the current value and returns the old value.
- */
- public fun getAndAdd(delta: Long): Long = this::value.getAndAddField(delta)
-
- /**
- * Atomically adds the [given value][delta] to the current value and returns the new value.
- */
- public fun addAndGet(delta: Long): Long = this::value.getAndAddField(delta) + delta
-
- /**
- * Atomically increments the current value by one and returns the old value.
- */
- public fun getAndIncrement(): Long = this::value.getAndAddField(1L)
-
- /**
- * Atomically increments the current value by one and returns the new value.
- */
- public fun incrementAndGet(): Long = this::value.getAndAddField(1L) + 1L
-
- /**
- * Atomically decrements the current value by one and returns the new value.
- */
- public fun decrementAndGet(): Long = this::value.getAndAddField(-1L) - 1L
-
- /**
- * Atomically decrements the current value by one and returns the old value.
- */
- public fun getAndDecrement(): Long = this::value.getAndAddField(-1L)
-
- /**
- * Returns the string representation of the current [value].
- */
- public override fun toString(): String = value.toString()
-}
-
-/**
- * An object reference that is always updated atomically.
- */
-@SinceKotlin("1.9")
-@Suppress("ACTUAL_WITHOUT_EXPECT") // actual visibility mismatch
-public actual class AtomicReference<T> actual constructor(public @Volatile actual var value: T) {
-
- /**
- * Atomically sets the value to the given [new value][newValue] and returns the old value.
- */
- public fun getAndSet(newValue: T): T = this::value.getAndSetField(newValue)
-
- /**
- * Atomically sets the value to the given [new value][newValue] if the current value equals the [expected value][expected],
- * returns true if the operation was successful and false only if the current value was not equal to the expected value.
- *
- * Provides sequential consistent ordering guarantees and cannot fail spuriously.
- *
- * Comparison of values is done by reference.
- */
- public actual fun compareAndSet(expected: T, newValue: T): Boolean = this::value.compareAndSetField(expected, newValue)
-
- /**
- * Atomically sets the value to the given [new value][newValue] if the current value equals the [expected value][expected]
- * and returns the old value in any case.
- *
- * Provides sequential consistent ordering guarantees and cannot fail spuriously.
- *
- * Comparison of values is done by reference.
- */
- public actual fun compareAndExchange(expected: T, newValue: T): T = this::value.compareAndExchangeField(expected, newValue)
-
- /**
- * Returns the string representation of the current [value].
- */
- public override fun toString(): String =
- "${debugString(this)} -> ${debugString(value)}"
-}
-
-/**
- * A [kotlinx.cinterop.NativePtr] value that is always updated atomically.
- * For additional details about atomicity guarantees for reads and writes see [kotlin.concurrent.Volatile].
- *
- * [kotlinx.cinterop.NativePtr] is a value type, hence it is stored in [AtomicNativePtr] without boxing
- * and [compareAndSet], [compareAndExchange] operations perform comparison by value.
- */
-@SinceKotlin("1.9")
-@ExperimentalForeignApi
-public class AtomicNativePtr(@Volatile public var value: NativePtr) {
- /**
- * Atomically sets the value to the given [new value][newValue] and returns the old value.
- */
- public fun getAndSet(newValue: NativePtr): NativePtr {
- // Pointer types are allowed for atomicrmw xchg operand since LLVM 15.0,
- // after LLVM version update, it may be implemented via getAndSetField intrinsic.
- // Check: https://youtrack.jetbrains.com/issue/KT-57557
- while (true) {
- val old = value
- if (this::value.compareAndSetField(old, newValue)) {
- return old
- }
- }
- }
-
- /**
- * Atomically sets the value to the given [new value][newValue] if the current value equals the [expected value][expected],
- * returns true if the operation was successful and false only if the current value was not equal to the expected value.
- *
- * Provides sequential consistent ordering guarantees and cannot fail spuriously.
- *
- * Comparison of values is done by value.
- */
- public fun compareAndSet(expected: NativePtr, newValue: NativePtr): Boolean =
- this::value.compareAndSetField(expected, newValue)
-
- /**
- * Atomically sets the value to the given [new value][newValue] if the current value equals the [expected value][expected]
- * and returns the old value in any case.
- *
- * Provides sequential consistent ordering guarantees and cannot fail spuriously.
- *
- * Comparison of values is done by value.
- */
- public fun compareAndExchange(expected: NativePtr, newValue: NativePtr): NativePtr =
- this::value.compareAndExchangeField(expected, newValue)
-
- /**
- * Returns the string representation of the current [value].
- */
- public override fun toString(): String = value.toString()
-}
-
-
-private fun idString(value: Any) = "${value.hashCode().toUInt().toString(16)}"
-
-private fun debugString(value: Any?): String {
- if (value == null) return "null"
- return "${value::class.qualifiedName}: ${idString(value)}"
-}
-
-/**
- * Atomically gets the value of the field referenced by [this].
- *
- * Provides sequential consistent ordering guarantees.
- *
- * This is equivalent to KMutableProperty0#get() invocation and used internally to optimize allocation of a property reference.
- *
- * For now, it can be used only within the same file, where property is defined.
- * Check https://youtrack.jetbrains.com/issue/KT-55426 for details.
- *
- * If [this] is not a compile-time known reference to the property with [Volatile] annotation [IllegalArgumentException]
- * would be thrown.
- *
- * If property referenced by [this] has nontrivial setter it will not be called.
- */
-@PublishedApi
-@TypedIntrinsic(IntrinsicType.ATOMIC_GET_FIELD)
-internal external fun <T> KMutableProperty0<T>.atomicGetField(): T
-
-/**
- * Atomically sets the value of the field referenced by [this] to the [new value][newValue].
- *
- * Provides sequential consistent ordering guarantees.
- *
- * This is equivalent to KMutableProperty0#set(value: T) invocation and used internally to optimize allocation of a property reference.
- *
- * For now, it can be used only within the same file, where property is defined.
- * Check https://youtrack.jetbrains.com/issue/KT-55426 for details.
- *
- * If [this] is not a compile-time known reference to the property with [Volatile] annotation [IllegalArgumentException]
- * would be thrown.
- *
- * If property referenced by [this] has nontrivial setter it will not be called.
- */
-@PublishedApi
-@TypedIntrinsic(IntrinsicType.ATOMIC_SET_FIELD)
-internal external fun <T> KMutableProperty0<T>.atomicSetField(newValue: T)
-
-/**
- * Atomically sets the value of the field referenced by [this] to the [new value][newValue]
- * if the current value equals the [expected value][expectedValue].
- * Returns true if the operation was successful and false only if the current value of the field was not equal to the expected value.
- *
- * Comparison is done by reference or value depending on field representation.
- *
- * Provides sequential consistent ordering guarantees and never fails spuriously.
- *
- * For now, it can be used only within the same file, where property is defined.
- * Check https://youtrack.jetbrains.com/issue/KT-55426 for details.
- *
- * If [this] is not a compile-time known reference to the property with [Volatile] annotation [IllegalArgumentException]
- * would be thrown.
- *
- * If property referenced by [this] has nontrivial setter it will not be called.
- */
-@PublishedApi
-@TypedIntrinsic(IntrinsicType.COMPARE_AND_SET_FIELD)
-internal external fun <T> KMutableProperty0<T>.compareAndSetField(expectedValue: T, newValue: T): Boolean
-
-/**
- * Atomically sets the value of the field referenced by [this] to the [new value][newValue]
- * if the current value equals the [expected value][expectedValue] and returns the old value of the field in any case.
- *
- * Comparison is done by reference or value depending on field representation.
- *
- * Provides sequential consistent ordering guarantees and never fails spuriously.
- *
- * For now, it can be used only within the same file, where property is defined.
- * Check https://youtrack.jetbrains.com/issue/KT-55426 for details.
- *
- * If [this] is not a compile-time known reference to the property with [Volatile] annotation [IllegalArgumentException]
- * would be thrown.
- *
- * If property referenced by [this] has nontrivial setter it will not be called.
- */
-@PublishedApi
-@TypedIntrinsic(IntrinsicType.COMPARE_AND_EXCHANGE_FIELD)
-internal external fun <T> KMutableProperty0<T>.compareAndExchangeField(expectedValue: T, newValue: T): T
-
-/**
- * Atomically sets the value of the field referenced by [this] to the [new value][newValue] and returns the old value of the field.
- *
- * Provides sequential consistent ordering guarantees.
- *
- * For now, it can be used only within the same file, where property is defined.
- * Check https://youtrack.jetbrains.com/issue/KT-55426 for details.
- *
- * If [this] is not a compile-time known reference to the property with [Volatile] annotation [IllegalArgumentException]
- * would be thrown.
- *
- * If property referenced by [this] has nontrivial setter it will not be called.
- */
-@PublishedApi
-@TypedIntrinsic(IntrinsicType.GET_AND_SET_FIELD)
-internal external fun <T> KMutableProperty0<T>.getAndSetField(newValue: T): T
-
-/**
- * Atomically adds the given [delta] to the value of the field referenced by [this] and returns the old value of the field.
- *
- * Provides sequential consistent ordering guarantees.
- *
- * For now, it can be used only within the same file, where property is defined.
- * Check https://youtrack.jetbrains.com/issue/KT-55426 for details.
- *
- * If [this] is not a compile-time known reference to the property with [Volatile] annotation [IllegalArgumentException]
- * would be thrown.
- *
- * If property referenced by [this] has nontrivial setter it will not be called.
- */
-@PublishedApi
-@TypedIntrinsic(IntrinsicType.GET_AND_ADD_FIELD)
-internal external fun KMutableProperty0<Short>.getAndAddField(delta: Short): Short
-
-/**
- * Atomically adds the given [delta] to the value of the field referenced by [this] and returns the old value of the field.
- *
- * Provides sequential consistent ordering guarantees.
- *
- * For now, it can be used only within the same file, where property is defined.
- * Check https://youtrack.jetbrains.com/issue/KT-55426 for details.
- *
- * If [this] is not a compile-time known reference to the property with [Volatile] annotation [IllegalArgumentException]
- * would be thrown.
- *
- * If property referenced by [this] has nontrivial setter it will not be called.
- */
-@PublishedApi
-@TypedIntrinsic(IntrinsicType.GET_AND_ADD_FIELD)
-internal external fun KMutableProperty0<Int>.getAndAddField(newValue: Int): Int
-
-/**
- * Atomically adds the given [delta] to the value of the field referenced by [this] and returns the old value of the field.
- *
- * Provides sequential consistent ordering guarantees.
- *
- * For now, it can be used only within the same file, where property is defined.
- * Check https://youtrack.jetbrains.com/issue/KT-55426 for details.
- *
- * If [this] is not a compile-time known reference to the property with [Volatile] annotation [IllegalArgumentException]
- * would be thrown.
- *
- * If property referenced by [this] has nontrivial setter it will not be called.
- */
-@PublishedApi
-@TypedIntrinsic(IntrinsicType.GET_AND_ADD_FIELD)
-internal external fun KMutableProperty0<Long>.getAndAddField(newValue: Long): Long
-
-/**
- * Atomically adds the given [delta] to the value of the field referenced by [this] and returns the old value of the field.
- *
- * Provides sequential consistent ordering guarantees.
- *
- * For now, it can be used only within the same file, where property is defined.
- * Check https://youtrack.jetbrains.com/issue/KT-55426 for details.
- *
- * If [this] is not a compile-time known reference to the property with [Volatile] annotation [IllegalArgumentException]
- * would be thrown.
- *
- * If property referenced by [this] has nontrivial setter it will not be called.
- */
-@PublishedApi
-@TypedIntrinsic(IntrinsicType.GET_AND_ADD_FIELD)
-internal external fun KMutableProperty0<Byte>.getAndAddField(newValue: Byte): Byte
diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/concurrent/Atomics.native.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/concurrent/Atomics.native.kt
new file mode 100644
index 0000000..4efb80d
--- /dev/null
+++ b/kotlin-native/runtime/src/main/kotlin/kotlin/concurrent/Atomics.native.kt
@@ -0,0 +1,635 @@
+/*
+ * Copyright 2010-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
+ * that can be found in the LICENSE file.
+ */
+
+package kotlin.concurrent
+
+import kotlinx.cinterop.NativePtr
+import kotlinx.cinterop.ExperimentalForeignApi
+import kotlin.native.internal.*
+import kotlin.reflect.*
+import kotlin.concurrent.*
+import kotlin.native.concurrent.*
+
+/**
+ * An [Int] value that may be updated atomically with guaranteed sequential consistent ordering.
+ *
+ * For additional details about atomicity guarantees for reads and writes see [kotlin.concurrent.Volatile].
+ */
+@Suppress("DEPRECATION")
+@SinceKotlin("1.9")
+public actual class AtomicInt public actual constructor(
+ @get:Deprecated("To read the atomic value use load().", ReplaceWith("this.load()"))
+ @set:Deprecated("To atomically set the new value use store(newValue: Int).", ReplaceWith("this.store(newValue)"))
+ public @Volatile var value: Int
+) {
+ /**
+ * Atomically gets the value of the atomic.
+ *
+ * Provides sequential consistent ordering guarantees.
+ */
+ public actual fun load(): Int = this::value.atomicGetField()
+
+ /**
+ * Atomically sets the value of the atomic to the [new value][newValue].
+ *
+ * Provides sequential consistent ordering guarantees.
+ */
+ public actual fun store(newValue: Int) { this::value.atomicSetField(value) }
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] and returns the old value.
+ */
+ public actual fun exchange(newValue: Int): Int = this::value.getAndSetField(newValue)
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] if the current value equals the [expected value][expectedValue],
+ * returns true if the operation was successful and false only if the current value was not equal to the expected value.
+ *
+ * Provides sequential consistent ordering guarantees and cannot fail spuriously.
+ *
+ * Comparison of values is done by value.
+ */
+ public actual fun compareAndSet(expectedValue: Int, newValue: Int): Boolean = this::value.compareAndSetField(expectedValue, newValue)
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] if the current value equals the [expected value][expected]
+ * and returns the old value in any case.
+ *
+ * Provides sequential consistent ordering guarantees and cannot fail spuriously.
+ *
+ * Comparison of values is done by value.
+ */
+ public actual fun compareAndExchange(expected: Int, newValue: Int): Int = this::value.compareAndExchangeField(expected, newValue)
+
+ /**
+ * Atomically adds the [given value][delta] to the current value and returns the old value.
+ */
+ public actual fun fetchAndAdd(delta: Int): Int = this::value.getAndAddField(delta)
+
+ /**
+ * Atomically adds the [given value][delta] to the current value and returns the new value.
+ */
+ public actual fun addAndFetch(delta: Int): Int = this::value.getAndAddField(delta) + delta
+
+ /**
+ * Atomically increments the current value by one and returns the old value.
+ */
+ public actual fun fetchAndIncrement(): Int = this::value.getAndAddField(1)
+
+ /**
+ * Atomically increments the current value by one and returns the new value.
+ */
+ public actual fun incrementAndFetch(): Int = this::value.getAndAddField(1) + 1
+
+ /**
+ * Atomically decrements the current value by one and returns the new value.
+ */
+ public actual fun decrementAndFetch(): Int = this::value.getAndAddField(-1) - 1
+
+ /**
+ * Atomically decrements the current value by one and returns the old value.
+ */
+ public actual fun fetchAndDecrement(): Int = this::value.getAndAddField(-1)
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] and returns the old value.
+ */
+ @Deprecated("Use exchange(newValue: Int) instead.", ReplaceWith("this.exchange(newValue)"))
+ public fun getAndSet(newValue: Int): Int = this::value.getAndSetField(newValue)
+
+ /**
+ * Atomically adds the [given value][delta] to the current value and returns the old value.
+ */
+ @Deprecated("Use fetchAndAdd(newValue: Int) instead.", ReplaceWith("this.fetchAndAdd(newValue)"))
+ public fun getAndAdd(delta: Int): Int = this::value.getAndAddField(delta)
+
+ /**
+ * Atomically adds the [given value][delta] to the current value and returns the new value.
+ */
+ @Deprecated("Use addAndFetch(newValue: Int) instead.", ReplaceWith("this.addAndFetch(newValue)"))
+ public fun addAndGet(delta: Int): Int = this::value.getAndAddField(delta) + delta
+
+ /**
+ * Atomically increments the current value by one and returns the old value.
+ */
+ @Deprecated("Use fetchAndIncrement() instead.", ReplaceWith("this.fetchAndIncrement()"))
+ public fun getAndIncrement(): Int = this::value.getAndAddField(1)
+
+ /**
+ * Atomically increments the current value by one and returns the new value.
+ */
+ @Deprecated("Use incrementAndFetch() instead.", ReplaceWith("this.incrementAndFetch()"))
+ public fun incrementAndGet(): Int = this::value.getAndAddField(1) + 1
+
+ /**
+ * Atomically decrements the current value by one and returns the new value.
+ */
+ @Deprecated("Use decrementAndFetch() instead.", ReplaceWith("this.decrementAndFetch()"))
+ public fun decrementAndGet(): Int = this::value.getAndAddField(-1) - 1
+
+ /**
+ * Atomically decrements the current value by one and returns the old value.
+ */
+ @Deprecated("Use fetchAndDecrement() instead.", ReplaceWith("this.fetchAndDecrement()"))
+ public fun getAndDecrement(): Int = this::value.getAndAddField(-1)
+
+ /**
+ * Returns the string representation of the underlying [Int] value.
+ *
+ * This operation does not provide any atomicity guarantees.
+ */
+ public actual override fun toString(): String = value.toString()
+}
+
+/**
+ * A [Long] value that may be updated atomically with guaranteed sequential consistent ordering.
+ *
+ * For additional details about atomicity guarantees for reads and writes see [kotlin.concurrent.Volatile].
+ */
+@Suppress("DEPRECATION")
+@SinceKotlin("1.9")
+public actual class AtomicLong public actual constructor(
+ @get:Deprecated("To read the atomic value use load().", ReplaceWith("this.load()"))
+ @set:Deprecated("To atomically set the new value use store(newValue: Long).", ReplaceWith("this.store(newValue)"))
+ public @Volatile var value: Long
+) {
+ /**
+ * Atomically gets the value of the atomic.
+ *
+ * Provides sequential consistent ordering guarantees.
+ */
+ public actual fun load(): Long = this::value.atomicGetField()
+
+ /**
+ * Atomically sets the value of the atomic to the [new value][newValue].
+ *
+ * Provides sequential consistent ordering guarantees.
+ */
+ public actual fun store(newValue: Long) { this::value.atomicSetField(value) }
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] and returns the old value.
+ */
+ public actual fun exchange(newValue: Long): Long = this::value.getAndSetField(newValue)
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] if the current value equals the [expected value][expected],
+ * returns true if the operation was successful and false only if the current value was not equal to the expected value.
+ *
+ * Provides sequential consistent ordering guarantees and cannot fail spuriously.
+ *
+ * Comparison of values is done by value.
+ */
+ public actual fun compareAndSet(expected: Long, newValue: Long): Boolean = this::value.compareAndSetField(expected, newValue)
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] if the current value equals the [expected value][expected]
+ * and returns the old value in any case.
+ *
+ * Provides sequential consistent ordering guarantees and cannot fail spuriously.
+ *
+ * Comparison of values is done by value.
+ */
+ public actual fun compareAndExchange(expected: Long, newValue: Long): Long = this::value.compareAndExchangeField(expected, newValue)
+
+ /**
+ * Atomically adds the [given value][delta] to the current value and returns the old value.
+ */
+ public actual fun fetchAndAdd(delta: Long): Long = this::value.getAndAddField(delta)
+
+ /**
+ * Atomically adds the [given value][delta] to the current value and returns the new value.
+ */
+ public actual fun addAndFetch(delta: Long): Long = this::value.getAndAddField(delta) + delta
+
+ /**
+ * Atomically increments the current value by one and returns the old value.
+ */
+ public actual fun fetchAndIncrement(): Long = this::value.getAndAddField(1L)
+
+ /**
+ * Atomically increments the current value by one and returns the new value.
+ */
+ public actual fun incrementAndFetch(): Long = this::value.getAndAddField(1L) + 1L
+
+ /**
+ * Atomically decrements the current value by one and returns the new value.
+ */
+ public actual fun decrementAndFetch(): Long = this::value.getAndAddField(-1L) - 1L
+
+ /**
+ * Atomically decrements the current value by one and returns the old value.
+ */
+ public actual fun fetchAndDecrement(): Long = this::value.getAndAddField(-1L)
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] and returns the old value.
+ */
+ @Deprecated("Use exchange(newValue: Long) instead.", ReplaceWith("this.exchange(newValue)"))
+ public fun getAndSet(newValue: Long): Long = this::value.getAndSetField(newValue)
+
+ /**
+ * Atomically adds the [given value][delta] to the current value and returns the old value.
+ */
+ @Deprecated("Use fetchAndAdd(newValue: Long) instead.", ReplaceWith("this.fetchAndAdd(newValue)"))
+ public fun getAndAdd(delta: Long): Long = this::value.getAndAddField(delta)
+
+ /**
+ * Atomically adds the [given value][delta] to the current value and returns the new value.
+ */
+ @Deprecated("Use addAndFetch(newValue: Long) instead.", ReplaceWith("this.addAndFetch(newValue)"))
+ public fun addAndGet(delta: Long): Long = this::value.getAndAddField(delta) + delta
+
+ /**
+ * Atomically increments the current value by one and returns the old value.
+ */
+ @Deprecated("Use fetchAndIncrement() instead.", ReplaceWith("this.fetchAndIncrement()"))
+ public fun getAndIncrement(): Long = this::value.getAndAddField(1L)
+
+ /**
+ * Atomically increments the current value by one and returns the new value.
+ */
+ @Deprecated("Use incrementAndFetch() instead.", ReplaceWith("this.incrementAndFetch()"))
+ public fun incrementAndGet(): Long = this::value.getAndAddField(1L) + 1L
+
+ /**
+ * Atomically decrements the current value by one and returns the new value.
+ */
+ @Deprecated("Use decrementAndFetch() instead.", ReplaceWith("this.decrementAndFetch()"))
+ public fun decrementAndGet(): Long = this::value.getAndAddField(-1L) - 1L
+
+ /**
+ * Atomically decrements the current value by one and returns the old value.
+ */
+ @Deprecated("Use fetchAndDecrement() instead.", ReplaceWith("this.fetchAndDecrement()"))
+ public fun getAndDecrement(): Long = this::value.getAndAddField(-1L)
+
+ /**
+ * Returns the string representation of the underlying [Long] value.
+ *
+ * This operation does not provide any atomicity guarantees.
+ */
+ public actual override fun toString(): String = value.toString()
+}
+
+/**
+ * A [Boolean] value that may be updated atomically with guaranteed sequential consistent ordering.
+ *
+ * For additional details about atomicity guarantees for reads and writes see [kotlin.concurrent.Volatile].
+ */
+public actual class AtomicBoolean actual constructor(private var value: Boolean) {
+
+ /**
+ * Atomically gets the value of the atomic.
+ *
+ * Provides sequential consistent ordering guarantees.
+ */
+ public actual fun load(): Boolean = this::value.atomicGetField()
+
+ /**
+ * Atomically sets the value of the atomic to the [new value][newValue].
+ *
+ * Provides sequential consistent ordering guarantees.
+ */
+ public actual fun store(newValue: Boolean) { this::value.atomicSetField(newValue) }
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] and returns the old value.
+ */
+ public actual fun exchange(newValue: Boolean): Boolean = this::value.getAndSetField(newValue)
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] if the current value equals the [expected value][expected],
+ * returns true if the operation was successful and false only if the current value was not equal to the expected value.
+ *
+ * Provides sequential consistent ordering guarantees and cannot fail spuriously.
+ *
+ * Comparison of values is done by value.
+ */
+ public actual fun compareAndSet(expected: Boolean, newValue: Boolean): Boolean = this::value.compareAndSetField(expected, newValue)
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] if the current value equals the [expected value][expected]
+ * and returns the old value in any case.
+ *
+ * Provides sequential consistent ordering guarantees and cannot fail spuriously.
+ *
+ * Comparison of values is done by value.
+ */
+ public actual fun compareAndExchange(expected: Boolean, newValue: Boolean): Boolean = this::value.compareAndExchangeField(expected, newValue)
+
+ /**
+ * Returns the string representation of the underlying [Boolean] value.
+ *
+ * This operation does not provide any atomicity guarantees.
+ */
+ public actual override fun toString(): String = value.toString()
+}
+
+/**
+ * An object reference that may be updated atomically with guaranteed sequential consistent ordering.
+ *
+ * For additional details about atomicity guarantees for reads and writes see [kotlin.concurrent.Volatile].
+ */
+@SinceKotlin("1.9")
+@Suppress("ACTUAL_WITHOUT_EXPECT", "DEPRECATION") // actual visibility mismatch
+public actual class AtomicReference<T> actual constructor(
+ @get:Deprecated("To read the atomic value use load().", ReplaceWith("this.load()"))
+ @set:Deprecated("To atomically set the new value use store(newValue: T).", ReplaceWith("this.store(newValue)"))
+ public @Volatile actual var value: T
+) {
+
+ /**
+ * Atomically gets the value of the atomic.
+ *
+ * Provides sequential consistent ordering guarantees.
+ */
+ public actual fun load(): T = this::value.atomicGetField()
+
+ /**
+ * Atomically sets the value of the atomic to the [new value][newValue].
+ *
+ * Provides sequential consistent ordering guarantees.
+ */
+ public actual fun store(newValue: T) { this::value.atomicSetField(newValue) }
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] and returns the old value.
+ */
+ public actual fun exchange(newValue: T): T = this::value.getAndSetField(newValue)
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] if the current value equals the [expected value][expected],
+ * returns true if the operation was successful and false only if the current value was not equal to the expected value.
+ *
+ * Provides sequential consistent ordering guarantees and cannot fail spuriously.
+ *
+ * Comparison of values is done by reference.
+ */
+ public actual fun compareAndSet(expected: T, newValue: T): Boolean = this::value.compareAndSetField(expected, newValue)
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] if the current value equals the [expected value][expected]
+ * and returns the old value in any case.
+ *
+ * Provides sequential consistent ordering guarantees and cannot fail spuriously.
+ *
+ * Comparison of values is done by reference.
+ */
+ public actual fun compareAndExchange(expected: T, newValue: T): T = this::value.compareAndExchangeField(expected, newValue)
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] and returns the old value.
+ */
+ @Deprecated("Use exchange(newValue: T) instead.", ReplaceWith("this.exchange(newValue)"))
+ public fun getAndSet(newValue: T): T = this::value.getAndSetField(newValue)
+
+ /**
+ * Returns the string representation of the underlying object.
+ *
+ * This operation does not provide any atomicity guarantees.
+ */
+ public actual override fun toString(): String =
+ "${debugString(this)} -> ${debugString(value)}"
+}
+
+/**
+ * A [kotlinx.cinterop.NativePtr] value that is always updated atomically.
+ * For additional details about atomicity guarantees for reads and writes see [kotlin.concurrent.Volatile].
+ *
+ * [kotlinx.cinterop.NativePtr] is a value type, hence it is stored in [AtomicNativePtr] without boxing
+ * and [compareAndSet], [compareAndExchange] operations perform comparison by value.
+ */
+@Suppress("DEPRECATION")
+@SinceKotlin("1.9")
+@ExperimentalForeignApi
+public class AtomicNativePtr(
+ @Deprecated("To read the atomic value use load(). To atomically set the new value use store(newValue: NativePtr).")
+ @Volatile public var value: NativePtr
+) {
+
+ public fun load(): NativePtr = this::value.atomicGetField()
+
+ public fun store(newValue: NativePtr) {
+ this::value.atomicSetField(newValue)
+ }
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] and returns the old value.
+ */
+ @Deprecated("Use exchange(newValue: Long) instead.", ReplaceWith("this.exchange(newValue)"))
+ public fun getAndSet(newValue: NativePtr): NativePtr {
+ // Pointer types are allowed for atomicrmw xchg operand since LLVM 15.0,
+ // after LLVM version update, it may be implemented via getAndSetField intrinsic.
+ // Check: https://youtrack.jetbrains.com/issue/KT-57557
+ while (true) {
+ val old = value
+ if (this::value.compareAndSetField(old, newValue)) {
+ return old
+ }
+ }
+ }
+
+ public fun exchange(newValue: NativePtr): NativePtr = getAndSet(newValue)
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] if the current value equals the [expected value][expected],
+ * returns true if the operation was successful and false only if the current value was not equal to the expected value.
+ *
+ * Provides sequential consistent ordering guarantees and cannot fail spuriously.
+ *
+ * Comparison of values is done by value.
+ */
+ public fun compareAndSet(expected: NativePtr, newValue: NativePtr): Boolean =
+ this::value.compareAndSetField(expected, newValue)
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] if the current value equals the [expected value][expected]
+ * and returns the old value in any case.
+ *
+ * Provides sequential consistent ordering guarantees and cannot fail spuriously.
+ *
+ * Comparison of values is done by value.
+ */
+ public fun compareAndExchange(expected: NativePtr, newValue: NativePtr): NativePtr =
+ this::value.compareAndExchangeField(expected, newValue)
+
+ /**
+ * Returns the string representation of the current [value].
+ */
+ public override fun toString(): String = value.toString()
+}
+
+
+private fun idString(value: Any) = "${value.hashCode().toUInt().toString(16)}"
+
+private fun debugString(value: Any?): String {
+ if (value == null) return "null"
+ return "${value::class.qualifiedName}: ${idString(value)}"
+}
+
+/**
+ * Atomically gets the value of the field referenced by [this].
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * This is equivalent to KMutableProperty0#get() invocation and used internally to optimize allocation of a property reference.
+ *
+ * For now, it can be used only within the same file, where property is defined.
+ * Check https://youtrack.jetbrains.com/issue/KT-55426 for details.
+ *
+ * If [this] is not a compile-time known reference to the property with [Volatile] annotation [IllegalArgumentException]
+ * would be thrown.
+ *
+ * If property referenced by [this] has nontrivial setter it will not be called.
+ */
+@PublishedApi
+@TypedIntrinsic(IntrinsicType.ATOMIC_GET_FIELD)
+internal external fun <T> KMutableProperty0<T>.atomicGetField(): T
+
+/**
+ * Atomically sets the value of the field referenced by [this] to the [new value][newValue].
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * This is equivalent to KMutableProperty0#set(value: T) invocation and used internally to optimize allocation of a property reference.
+ *
+ * For now, it can be used only within the same file, where property is defined.
+ * Check https://youtrack.jetbrains.com/issue/KT-55426 for details.
+ *
+ * If [this] is not a compile-time known reference to the property with [Volatile] annotation [IllegalArgumentException]
+ * would be thrown.
+ *
+ * If property referenced by [this] has nontrivial setter it will not be called.
+ */
+@PublishedApi
+@TypedIntrinsic(IntrinsicType.ATOMIC_SET_FIELD)
+internal external fun <T> KMutableProperty0<T>.atomicSetField(newValue: T)
+
+/**
+ * Atomically sets the value of the field referenced by [this] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue].
+ * Returns true if the operation was successful and false only if the current value of the field was not equal to the expected value.
+ *
+ * Comparison is done by reference or value depending on field representation.
+ *
+ * Provides sequential consistent ordering guarantees and never fails spuriously.
+ *
+ * For now, it can be used only within the same file, where property is defined.
+ * Check https://youtrack.jetbrains.com/issue/KT-55426 for details.
+ *
+ * If [this] is not a compile-time known reference to the property with [Volatile] annotation [IllegalArgumentException]
+ * would be thrown.
+ *
+ * If property referenced by [this] has nontrivial setter it will not be called.
+ */
+@PublishedApi
+@TypedIntrinsic(IntrinsicType.COMPARE_AND_SET_FIELD)
+internal external fun <T> KMutableProperty0<T>.compareAndSetField(expectedValue: T, newValue: T): Boolean
+
+/**
+ * Atomically sets the value of the field referenced by [this] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue] and returns the old value of the field in any case.
+ *
+ * Comparison is done by reference or value depending on field representation.
+ *
+ * Provides sequential consistent ordering guarantees and never fails spuriously.
+ *
+ * For now, it can be used only within the same file, where property is defined.
+ * Check https://youtrack.jetbrains.com/issue/KT-55426 for details.
+ *
+ * If [this] is not a compile-time known reference to the property with [Volatile] annotation [IllegalArgumentException]
+ * would be thrown.
+ *
+ * If property referenced by [this] has nontrivial setter it will not be called.
+ */
+@PublishedApi
+@TypedIntrinsic(IntrinsicType.COMPARE_AND_EXCHANGE_FIELD)
+internal external fun <T> KMutableProperty0<T>.compareAndExchangeField(expectedValue: T, newValue: T): T
+
+/**
+ * Atomically sets the value of the field referenced by [this] to the [new value][newValue] and returns the old value of the field.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * For now, it can be used only within the same file, where property is defined.
+ * Check https://youtrack.jetbrains.com/issue/KT-55426 for details.
+ *
+ * If [this] is not a compile-time known reference to the property with [Volatile] annotation [IllegalArgumentException]
+ * would be thrown.
+ *
+ * If property referenced by [this] has nontrivial setter it will not be called.
+ */
+@PublishedApi
+@TypedIntrinsic(IntrinsicType.GET_AND_SET_FIELD)
+internal external fun <T> KMutableProperty0<T>.getAndSetField(newValue: T): T
+
+/**
+ * Atomically adds the given [delta] to the value of the field referenced by [this] and returns the old value of the field.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * For now, it can be used only within the same file, where property is defined.
+ * Check https://youtrack.jetbrains.com/issue/KT-55426 for details.
+ *
+ * If [this] is not a compile-time known reference to the property with [Volatile] annotation [IllegalArgumentException]
+ * would be thrown.
+ *
+ * If property referenced by [this] has nontrivial setter it will not be called.
+ */
+@PublishedApi
+@TypedIntrinsic(IntrinsicType.GET_AND_ADD_FIELD)
+internal external fun KMutableProperty0<Short>.getAndAddField(delta: Short): Short
+
+/**
+ * Atomically adds the given [delta] to the value of the field referenced by [this] and returns the old value of the field.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * For now, it can be used only within the same file, where property is defined.
+ * Check https://youtrack.jetbrains.com/issue/KT-55426 for details.
+ *
+ * If [this] is not a compile-time known reference to the property with [Volatile] annotation [IllegalArgumentException]
+ * would be thrown.
+ *
+ * If property referenced by [this] has nontrivial setter it will not be called.
+ */
+@PublishedApi
+@TypedIntrinsic(IntrinsicType.GET_AND_ADD_FIELD)
+internal external fun KMutableProperty0<Int>.getAndAddField(newValue: Int): Int
+
+/**
+ * Atomically adds the given [delta] to the value of the field referenced by [this] and returns the old value of the field.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * For now, it can be used only within the same file, where property is defined.
+ * Check https://youtrack.jetbrains.com/issue/KT-55426 for details.
+ *
+ * If [this] is not a compile-time known reference to the property with [Volatile] annotation [IllegalArgumentException]
+ * would be thrown.
+ *
+ * If property referenced by [this] has nontrivial setter it will not be called.
+ */
+@PublishedApi
+@TypedIntrinsic(IntrinsicType.GET_AND_ADD_FIELD)
+internal external fun KMutableProperty0<Long>.getAndAddField(newValue: Long): Long
+
+/**
+ * Atomically adds the given [delta] to the value of the field referenced by [this] and returns the old value of the field.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * For now, it can be used only within the same file, where property is defined.
+ * Check https://youtrack.jetbrains.com/issue/KT-55426 for details.
+ *
+ * If [this] is not a compile-time known reference to the property with [Volatile] annotation [IllegalArgumentException]
+ * would be thrown.
+ *
+ * If property referenced by [this] has nontrivial setter it will not be called.
+ */
+@PublishedApi
+@TypedIntrinsic(IntrinsicType.GET_AND_ADD_FIELD)
+internal external fun KMutableProperty0<Byte>.getAndAddField(newValue: Byte): Byte
diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/coroutines/SafeContinuationNative.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/coroutines/SafeContinuationNative.kt
index 211bb76..c7d5f93 100644
--- a/kotlin-native/runtime/src/main/kotlin/kotlin/coroutines/SafeContinuationNative.kt
+++ b/kotlin-native/runtime/src/main/kotlin/kotlin/coroutines/SafeContinuationNative.kt
@@ -28,7 +28,7 @@
public actual override fun resumeWith(result: Result<T>) {
while (true) {
- val cur = resultRef.value
+ val cur = resultRef.load()
when {
cur === UNDECIDED -> if (resultRef.compareAndSet(UNDECIDED, result.value)) return
cur === COROUTINE_SUSPENDED -> if (resultRef.compareAndSet(COROUTINE_SUSPENDED, RESUMED)) {
@@ -42,10 +42,10 @@
@PublishedApi
internal actual fun getOrThrow(): Any? {
- var result = resultRef.value
+ var result = resultRef.load()
if (result === UNDECIDED) {
if (resultRef.compareAndSet(UNDECIDED, COROUTINE_SUSPENDED)) return COROUTINE_SUSPENDED
- result = resultRef.value
+ result = resultRef.load()
}
return when {
result === RESUMED -> COROUTINE_SUSPENDED // already called continuation, indicate COROUTINE_SUSPENDED upstream
diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/Runtime.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/Runtime.kt
index af15da6..0577606 100644
--- a/kotlin-native/runtime/src/main/kotlin/kotlin/native/Runtime.kt
+++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/Runtime.kt
@@ -46,7 +46,7 @@
*/
@ExperimentalNativeApi
public fun setUnhandledExceptionHook(hook: ReportUnhandledExceptionHook?): ReportUnhandledExceptionHook? {
- return UnhandledExceptionHookHolder.hook.getAndSet(hook)
+ return UnhandledExceptionHookHolder.hook.exchange(hook)
}
/**
@@ -55,7 +55,7 @@
@ExperimentalNativeApi
@SinceKotlin("1.6")
public fun getUnhandledExceptionHook(): ReportUnhandledExceptionHook? {
- return UnhandledExceptionHookHolder.hook.value
+ return UnhandledExceptionHookHolder.hook.load()
}
/**
diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Lazy.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Lazy.kt
index 9dc55a02..0a8efdc 100644
--- a/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Lazy.kt
+++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Lazy.kt
@@ -25,7 +25,7 @@
get() {
if (value_.compareAndExchange(UNINITIALIZED, INITIALIZING) === UNINITIALIZED) {
// We execute exclusively here.
- val ctor = initializer_.value
+ val ctor = initializer_.load()
if (ctor != null && initializer_.compareAndSet(ctor, null)) {
value_.compareAndSet(INITIALIZING, ctor())
} else {
@@ -35,7 +35,7 @@
}
var result: Any?
do {
- result = value_.value
+ result = value_.load()
} while (result === INITIALIZING)
assert(result !== UNINITIALIZED && result !== INITIALIZING)
@@ -43,10 +43,10 @@
return result as T
}
- override fun isInitialized(): Boolean = value_.value !== UNINITIALIZED
+ override fun isInitialized(): Boolean = value_.load() !== UNINITIALIZED
override fun toString(): String = if (isInitialized())
- value_.value.toString() else "Lazy value not initialized yet."
+ value_.load().toString() else "Lazy value not initialized yet."
}
/**
diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Lock.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Lock.kt
index 18d07d3..a2158fd 100644
--- a/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Lock.kt
+++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Lock.kt
@@ -26,12 +26,12 @@
when (old) {
lockData -> {
// Was locked by us already.
- reenterCount_.incrementAndGet()
+ reenterCount_.incrementAndFetch()
break@loop
}
0 -> {
// We just got the lock.
- assert(reenterCount_.value == 0)
+ assert(reenterCount_.load() == 0)
break@loop
}
}
@@ -39,8 +39,8 @@
}
fun unlock() {
- if (reenterCount_.value > 0) {
- reenterCount_.decrementAndGet()
+ if (reenterCount_.load() > 0) {
+ reenterCount_.decrementAndFetch()
} else {
val lockData = CurrentThread.id.hashCode()
val old = locker_.compareAndExchange(lockData, 0)
diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/ObjectTransfer.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/ObjectTransfer.kt
index eaad95e..4b5b271 100644
--- a/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/ObjectTransfer.kt
+++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/ObjectTransfer.kt
@@ -76,7 +76,7 @@
* Returns raw C pointer value, usable for interoperability with C scenarious.
*/
@ExperimentalForeignApi
- public fun asCPointer(): COpaquePointer? = interpretCPointer<COpaque>(stable.value)
+ public fun asCPointer(): COpaquePointer? = interpretCPointer<COpaque>(stable.load())
}
/**
@@ -90,7 +90,7 @@
public inline fun <reified T> DetachedObjectGraph<T>.attach(): T {
var rawStable: NativePtr
do {
- rawStable = stable.value
+ rawStable = stable.load()
} while (!stable.compareAndSet(rawStable, NativePtr.NULL))
val result = attachObjectGraphInternal(rawStable) as T
return result
diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/RuntimeUtils.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/RuntimeUtils.kt
index fbb946d..5a26d7f 100644
--- a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/RuntimeUtils.kt
+++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/RuntimeUtils.kt
@@ -160,7 +160,7 @@
@ExportForCppRuntime
@OptIn(ExperimentalNativeApi::class)
internal fun OnUnhandledException(throwable: Throwable) {
- val handler = UnhandledExceptionHookHolder.hook.value
+ val handler = UnhandledExceptionHookHolder.hook.load()
if (handler == null) {
ReportUnhandledException(throwable);
return
@@ -175,7 +175,7 @@
@ExportForCppRuntime("Kotlin_runUnhandledExceptionHook")
@OptIn(ExperimentalNativeApi::class)
internal fun runUnhandledExceptionHook(throwable: Throwable) {
- val handler = UnhandledExceptionHookHolder.hook.value ?: throw throwable
+ val handler = UnhandledExceptionHookHolder.hook.load() ?: throw throwable
handler(throwable)
}
diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/random/Random.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/random/Random.kt
index 8184728..cb0b6e9 100644
--- a/kotlin-native/runtime/src/main/kotlin/kotlin/random/Random.kt
+++ b/kotlin-native/runtime/src/main/kotlin/kotlin/random/Random.kt
@@ -19,12 +19,12 @@
* Random generator seed value.
*/
private val seed: Long
- get() = _seed.value
+ get() = _seed.load()
private fun mult(value: Long) = (value xor MULTIPLIER) and ((1L shl 48) - 1)
private fun update(seed: Long): Unit {
- _seed.value = seed
+ _seed.store(seed)
}
override fun nextBits(bitCount: Int): Int {
diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/sequences/Sequences.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/sequences/Sequences.kt
index 0612d88..a1dbb4f 100644
--- a/kotlin-native/runtime/src/main/kotlin/kotlin/sequences/Sequences.kt
+++ b/kotlin-native/runtime/src/main/kotlin/kotlin/sequences/Sequences.kt
@@ -11,7 +11,7 @@
private val sequenceRef = kotlin.concurrent.AtomicReference<Sequence<T>?>(sequence)
override actual fun iterator(): Iterator<T> {
- val sequence = sequenceRef.getAndSet(null) ?: throw IllegalStateException("This sequence can be consumed only once.")
+ val sequence = sequenceRef.exchange(null) ?: throw IllegalStateException("This sequence can be consumed only once.")
return sequence.iterator()
}
}
diff --git a/kotlin-native/runtime/test/concurrent/AtomicArrayTest.kt b/kotlin-native/runtime/test/concurrent/AtomicArrayTest.kt
deleted file mode 100644
index a6f29af..0000000
--- a/kotlin-native/runtime/test/concurrent/AtomicArrayTest.kt
+++ /dev/null
@@ -1,570 +0,0 @@
-/*
- * Copyright 2010-2023 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.
- */
-
-package test.concurrent
-
-import kotlin.concurrent.*
-import kotlin.test.*
-
-class AtomicIntArrayTest {
- @Test fun ctor() {
- val arr1 = AtomicIntArray(6)
- assertEquals(arr1[4], 0)
- assertEquals(arr1.length, 6)
-
- val arr2 = AtomicIntArray(10) { i: Int -> i * 10 }
- assertEquals(arr2[4], 40)
- assertEquals(arr2.length, 10)
-
- val emptyArr = AtomicIntArray(0)
- assertEquals(emptyArr.length, 0)
-
- assertFailsWith<IllegalArgumentException> {
- val arrNegativeSize = AtomicIntArray(-5)
- }
- }
-
- @Test fun getter() {
- val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
- for (i in 0 until atomicIntArr.length) {
- assertEquals(i * 10, atomicIntArr[i], "getter: FAIL $i")
- }
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicIntArr[22]
- }.let { ex ->
- assertEquals("The index 22 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicIntArr[-1]
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
- }
- }
-
- @Test fun setter() {
- val atomicIntArr = AtomicIntArray(10)
- for (i in 0 until atomicIntArr.length) {
- atomicIntArr[i] = i * 10
- }
- for (i in 0 until atomicIntArr.length) {
- assertEquals(i * 10, atomicIntArr[i], "setter: FAIL $i")
- }
- assertFailsWith<IndexOutOfBoundsException> {
- atomicIntArr[22] = 100
- }.let { ex ->
- assertEquals("The index 22 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- atomicIntArr[-1] = 100
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
- }
- }
-
- @Test fun addAndGet() {
- val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
- assertEquals(110, atomicIntArr.addAndGet(1, 100), "addAndGet: FAIL 1")
- assertEquals(110, atomicIntArr[1], "addAndGet: FAIL 2")
- assertEquals(10, atomicIntArr.addAndGet(1, -100), "addAndGet: FAIL 3")
- assertEquals(10, atomicIntArr[1], "addAndGet: FAIL 4")
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicIntArr.addAndGet(22, 33535)
- }.let { ex ->
- assertEquals("The index 22 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicIntArr.addAndGet(-1, 33535)
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
- }
- }
-
- @Test fun compareAndExchange() {
- val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
- val res1 = atomicIntArr.compareAndExchange(2, 20, 222) // success
- assertTrue(res1 == 20 && atomicIntArr[2] == 222, "compareAndExchange: FAIL 1")
- val res2 = atomicIntArr.compareAndExchange(2, 222, 2222) // success
- assertTrue(res2 == 222 && atomicIntArr[2] == 2222, "compareAndExchange: FAIL 2")
- val res3 = atomicIntArr.compareAndExchange(2, 223, 22222) // should fail
- assertTrue(res3 == 2222 && atomicIntArr[2] == 2222, "compareAndExchange: FAIL 3")
- val res4 = atomicIntArr.compareAndExchange(9, 10, 999) // should fail
- assertTrue(res4 == 90 && atomicIntArr[9] == 90, "compareAndExchange: FAIL 4")
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicIntArr.compareAndExchange(10, 33535, 39530)
- }.let { ex ->
- assertEquals("The index 10 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicIntArr.compareAndExchange(-1, 33535, 39530)
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
- }
- }
-
- @Test fun compareAndSet() {
- val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
- val res1 = atomicIntArr.compareAndSet(2, 20, 222) // success
- assertTrue(res1 && atomicIntArr[2] == 222, "compareAndSet: FAIL 1")
- val res2 = atomicIntArr.compareAndSet(2, 222, 2222) // success
- assertTrue(res2 && atomicIntArr[2] == 2222, "compareAndSet: FAIL 2")
- val res3 = atomicIntArr.compareAndSet(2, 223, 22222) // should fail
- assertTrue(!res3 && atomicIntArr[2] == 2222, "compareAndSet: FAIL 3")
- val res4 = atomicIntArr.compareAndSet(9, 10, 999) // should fail
- assertTrue(!res4 && atomicIntArr[9] == 90, "compareAndSet: FAIL 4")
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicIntArr.compareAndSet(10, 33535, 39530)
- }.let { ex ->
- assertEquals("The index 10 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicIntArr.compareAndSet(-1, 33535, 39530)
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
- }
- }
-
- @Test fun getAndSet() {
- val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
- assertEquals(20, atomicIntArr.getAndSet(2, 200), "getAndSet: FAIL 1")
- assertEquals(200, atomicIntArr.getAndSet(2, 2000), "getAndSet: FAIL 2")
- assertEquals(2000, atomicIntArr[2], "getAndSet: FAIL 3")
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicIntArr.getAndSet(22, 33535)
- }.let { ex ->
- assertEquals("The index 22 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicIntArr.getAndSet(-1, 33535)
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
- }
- }
-
- @Test fun getAndAdd() {
- val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
- assertEquals(10, atomicIntArr.getAndAdd(1, 100), "getAndAdd: FAIL 1")
- assertEquals(110, atomicIntArr[1], "getAndAdd: FAIL 2")
- assertEquals(110, atomicIntArr.getAndAdd(1, -100), "getAndAdd: FAIL 3")
- assertEquals(10, atomicIntArr[1], "getAndAdd: FAIL 4")
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicIntArr.getAndAdd(22, 33535)
- }.let { ex ->
- assertEquals("The index 22 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicIntArr.getAndAdd(-1, 33535)
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
- }
- }
-
- @Test fun getAndIncrement() {
- val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
- assertEquals(10, atomicIntArr.getAndIncrement(1), "getAndIncrement: FAIL 1")
- assertEquals(11, atomicIntArr[1], "getAndIncrement: FAIL 2")
- assertEquals(11, atomicIntArr.getAndIncrement(1), "getAndIncrement: FAIL 3")
- assertEquals(12, atomicIntArr[1], "getAndIncrement: FAIL 4")
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicIntArr.getAndIncrement(22)
- }.let { ex ->
- assertEquals("The index 22 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicIntArr.getAndIncrement(-1)
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
- }
- }
-
- @Test fun incrementAndGet() {
- val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
- assertEquals(11, atomicIntArr.incrementAndGet(1), "incrementAndGet: FAIL 1")
- assertEquals(11, atomicIntArr[1], "incrementAndGet: FAIL 2")
- assertEquals(12, atomicIntArr.incrementAndGet(1), "incrementAndGet: FAIL 3")
- assertEquals(12, atomicIntArr[1], "incrementAndGet: FAIL 4")
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicIntArr.incrementAndGet(22)
- }.let { ex ->
- assertEquals("The index 22 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicIntArr.incrementAndGet(-1)
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
- }
- }
-
- @Test fun getAndDecrement() {
- val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
- assertEquals(10, atomicIntArr.getAndDecrement(1), "getAndDecrement: FAIL 1")
- assertEquals(9, atomicIntArr[1], "getAndDecrement: FAIL 2")
- assertEquals(9, atomicIntArr.getAndDecrement(1), "getAndDecrement: FAIL 3")
- assertEquals(8, atomicIntArr[1], "getAndDecrement: FAIL 4")
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicIntArr.getAndDecrement(22)
- }.let { ex ->
- assertEquals("The index 22 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicIntArr.getAndDecrement(-1)
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
- }
- }
-
- @Test fun decrementAndGet() {
- val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
- assertEquals(9, atomicIntArr.decrementAndGet(1), "decrementAndGet: FAIL 1")
- assertEquals(9, atomicIntArr[1], "decrementAndGet: FAIL 2")
- assertEquals(8, atomicIntArr.decrementAndGet(1), "decrementAndGet: FAIL 3")
- assertEquals(8, atomicIntArr[1], "decrementAndGet: FAIL 4")
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicIntArr.decrementAndGet(22)
- }.let { ex ->
- assertEquals("The index 22 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicIntArr.decrementAndGet(-1)
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
- }
- }
-}
-
-class AtomicLongArrayTest {
- @Test fun ctor() {
- val arr1 = AtomicLongArray(6)
- assertEquals(arr1[4], 0L)
- assertEquals(arr1.length, 6)
- val arr2 = AtomicLongArray(10) { i: Int -> i * 10L }
- assertEquals(arr2[4], 40L)
- assertEquals(arr2.length, 10)
-
- val emptyArr = AtomicLongArray(0)
- assertEquals(emptyArr.length, 0)
-
- assertFailsWith<IllegalArgumentException> {
- val arrNegativeSize = AtomicLongArray(-5)
- }
- }
-
- @Test fun getter() {
- val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
- for (i in 0 until atomicLongArr.length) {
- assertEquals(i * 10L, atomicLongArr[i], "getter: FAIL $i")
- }
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicLongArr[22]
- }.let { ex ->
- assertEquals("The index 22 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicLongArr[-1]
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
- }
- }
-
- @Test fun setter() {
- val atomicLongArr = AtomicLongArray(10)
- for (i in 0 until atomicLongArr.length) {
- atomicLongArr[i] = i * 10L
- }
- for (i in 0 until atomicLongArr.length) {
- assertEquals(i * 10L, atomicLongArr[i], "setter: FAIL $i")
- }
- assertFailsWith<IndexOutOfBoundsException> {
- atomicLongArr[10] = 3998009
- }.let { ex ->
- assertEquals("The index 10 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- atomicLongArr[-1] = 3998009
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
- }
- }
-
- @Test fun addAndGet() {
- val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
- assertEquals(110L, atomicLongArr.addAndGet(1, 100L), "addAndGet: FAIL 1")
- assertEquals(110L, atomicLongArr[1], "addAndGet: FAIL 2")
- assertEquals(10L, atomicLongArr.addAndGet(1, -100L), "addAndGet: FAIL 3")
- assertEquals(10L, atomicLongArr[1], "addAndGet: FAIL 4")
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicLongArr.addAndGet(22, 33535)
- }.let { ex ->
- assertEquals("The index 22 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicLongArr.addAndGet(-1, 33535)
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
- }
- }
-
- @Test fun compareAndExchange() {
- val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
- val res1 = atomicLongArr.compareAndExchange(2, 20L, 222L) // success
- assertTrue(res1 == 20L && atomicLongArr[2] == 222L, "compareAndExchange: FAIL 1")
- val res2 = atomicLongArr.compareAndExchange(2, 222L, 2222L) // success
- assertTrue(res2 == 222L && atomicLongArr[2] == 2222L, "compareAndExchange: FAIL 2")
- val res3 = atomicLongArr.compareAndExchange(2, 223L, 22222L) // should fail
- assertTrue(res3 == 2222L && atomicLongArr[2] == 2222L, "compareAndExchange: FAIL 3")
- val res4 = atomicLongArr.compareAndExchange(9, 10L, 999L) // should fail
- assertTrue(res4 == 90L && atomicLongArr[9] == 90L, "compareAndExchange: FAIL 4")
- assertFailsWith<IndexOutOfBoundsException> {
- atomicLongArr.compareAndExchange(10, 9353, 39058308)
- }.let { ex ->
- assertEquals("The index 10 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- atomicLongArr.compareAndExchange(-1, 9353, 39058308)
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
- }
- }
-
- @Test fun compareAndSet() {
- val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
- val res1 = atomicLongArr.compareAndSet(2, 20L, 222L) // success
- assertTrue(res1 && atomicLongArr[2] == 222L, "compareAndSet: FAIL 1")
- val res2 = atomicLongArr.compareAndSet(2, 222L, 2222L) // success
- assertTrue(res2 && atomicLongArr[2] == 2222L, "compareAndSet: FAIL 2")
- val res3 = atomicLongArr.compareAndSet(2, 223L, 22222L) // should fail
- assertTrue(!res3 && atomicLongArr[2] == 2222L, "compareAndSet: FAIL 3")
- val res4 = atomicLongArr.compareAndSet(9, 10L, 999L) // should fail
- assertTrue(!res4 && atomicLongArr[9] == 90L, "compareAndSet: FAIL 4")
- assertFailsWith<IndexOutOfBoundsException> {
- atomicLongArr.compareAndSet(10, 9353, 39058308)
- }.let { ex ->
- assertEquals("The index 10 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- atomicLongArr.compareAndSet(-1, 9353, 39058308)
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
- }
- }
-
- @Test fun getAndSet() {
- val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
- assertEquals(20L, atomicLongArr.getAndSet(2, 200L), "getAndSet: FAIL 1")
- assertEquals(200L, atomicLongArr.getAndSet(2, 2000L), "getAndSet: FAIL 2")
- assertEquals(2000L, atomicLongArr[2], "getAndSet: FAIL 3")
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicLongArr.getAndSet(22, 9353)
- }.let { ex ->
- assertEquals("The index 22 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicLongArr.getAndSet(-1, 9353)
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
- }
- }
-
- @Test fun getAndAdd() {
- val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
- assertEquals(10L, atomicLongArr.getAndAdd(1, 100L), "getAndAdd: FAIL 1")
- assertEquals(110L, atomicLongArr[1], "getAndAdd: FAIL 2")
- assertEquals(110L, atomicLongArr.getAndAdd(1, -100L), "getAndAdd: FAIL 3")
- assertEquals(10L, atomicLongArr[1], "getAndAdd: FAIL 4")
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicLongArr.getAndAdd(100, 9353)
- }.let { ex ->
- assertEquals("The index 100 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicLongArr.getAndAdd(-1, 9353)
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
- }
- }
-
- @Test fun getAndIncrement() {
- val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
- assertEquals(10L, atomicLongArr.getAndIncrement(1), "getAndIncrement: FAIL 1")
- assertEquals(11L, atomicLongArr[1], "getAndIncrement: FAIL 2")
- assertEquals(11L, atomicLongArr.getAndIncrement(1), "getAndIncrement: FAIL 3")
- assertEquals(12L, atomicLongArr[1], "getAndIncrement: FAIL 4")
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicLongArr.getAndIncrement(22)
- }.let { ex ->
- assertEquals("The index 22 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicLongArr.addAndGet(-1, 33535)
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
- }
- }
-
- @Test fun incrementAndGet() {
- val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
- assertEquals(11L, atomicLongArr.incrementAndGet(1), "incrementAndGet: FAIL 1")
- assertEquals(11L, atomicLongArr[1], "incrementAndGet: FAIL 2")
- assertEquals(12L, atomicLongArr.incrementAndGet(1), "incrementAndGet: FAIL 3")
- assertEquals(12L, atomicLongArr[1], "incrementAndGet: FAIL 4")
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicLongArr.incrementAndGet(22)
- }.let { ex ->
- assertEquals("The index 22 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicLongArr.incrementAndGet(-1)
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
- }
- }
-
- @Test fun getAndDecrement() {
- val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
- assertEquals(10L, atomicLongArr.getAndDecrement(1), "getAndDecrement: FAIL 1")
- assertEquals(9L, atomicLongArr[1], "getAndDecrement: FAIL 2")
- assertEquals(9L, atomicLongArr.getAndDecrement(1), "getAndDecrement: FAIL 3")
- assertEquals(8L, atomicLongArr[1], "getAndDecrement: FAIL 4")
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicLongArr.getAndDecrement(22)
- }.let { ex ->
- assertEquals("The index 22 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicLongArr.getAndDecrement(-1)
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
- }
- }
-
- @Test fun decrementAndGet() {
- val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
- assertEquals(9L, atomicLongArr.decrementAndGet(1), "decrementAndGet: FAIL 1")
- assertEquals(9L, atomicLongArr[1], "decrementAndGet: FAIL 2")
- assertEquals(8L, atomicLongArr.decrementAndGet(1), "decrementAndGet: FAIL 3")
- assertEquals(8L, atomicLongArr[1], "decrementAndGet: FAIL 4")
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicLongArr.decrementAndGet(22)
- }.let { ex ->
- assertEquals("The index 22 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- val res = atomicLongArr.decrementAndGet(-1)
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
- }
- }
-}
-
-class AtomicArrayTest {
- @Test fun ctor() {
- val arr2 = AtomicArray<Data?>(10) { null }
- assertEquals(arr2[4], null)
- assertEquals(arr2.length, 10)
-
- val emptyArr = AtomicArray<Data?>(0) { Data(1) }
- assertEquals(emptyArr.length, 0)
-
- assertFailsWith<IllegalArgumentException> {
- val arrNegativeSize = AtomicArray<Data?>(-5) { Data(1) }
- }
- }
-
- @Test fun getter() {
- val refArr = AtomicArray<Data?>(10) { i -> Data(i) }
- for (i in 0 until refArr.length) {
- assertEquals(Data(i), refArr[i], "getter: FAIL $i")
- }
- assertFailsWith<IndexOutOfBoundsException> {
- val res = refArr[100]
- }.let { ex ->
- assertEquals("The index 100 is out of the bounds of the AtomicArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- val res = refArr[-1]
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicArray with size 10.", ex.message)
- }
- }
-
- @Test fun setter() {
- val refArr = AtomicArray<Data?>(10) { null }
- for (i in 0 until refArr.length) {
- refArr[i] = Data(i)
- }
- for (i in 0 until refArr.length) {
- assertEquals(Data(i), refArr[i], "setter: FAIL $i")
- }
- assertFailsWith<IndexOutOfBoundsException> {
- refArr[100] = Data(100)
- }.let { ex ->
- assertEquals("The index 100 is out of the bounds of the AtomicArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- refArr[-1] = Data(-1)
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicArray with size 10.", ex.message)
- }
- }
-
- @Test fun compareAndExchange() {
- val refArr = AtomicArray<Data?>(10) { null }
- val newValue = Data(1)
- val res1 = refArr.compareAndExchange(3, null, newValue)
- assertTrue(res1 == null && refArr[3] == newValue, "compareAndExchange: FAIL 1")
- val res2 = refArr.compareAndExchange(3, newValue, Data(2))
- assertTrue(res2 == newValue && refArr[3] == Data(2), "compareAndExchange: FAIL 2")
- val res3 = refArr.compareAndExchange(3, newValue, Data(3))
- assertTrue(res3 == Data(2) && refArr[3] == Data(2), "compareAndExchange: FAIL 3")
- assertFailsWith<IndexOutOfBoundsException> {
- refArr.compareAndExchange(10, newValue, Data(4))
- }.let { ex ->
- assertEquals("The index 10 is out of the bounds of the AtomicArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- refArr.compareAndExchange(-1, newValue, Data(4))
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicArray with size 10.", ex.message)
- }
- }
-
- @Test fun compareAndSet() {
- val refArr = AtomicArray<Data?>(10) { null }
- val newValue = Data(1)
- val res1 = refArr.compareAndSet(3, null, newValue)
- assertTrue(res1 && refArr[3] == newValue, "testAtomicArrayCompareAndSet: FAIL 1")
- val res2 = refArr.compareAndSet(3, newValue, Data(2))
- assertTrue(res2 && refArr[3] == Data(2), "testAtomicArrayCompareAndSet: FAIL 2")
- val res3 = refArr.compareAndSet(3, newValue, Data(3))
- assertTrue(!res3 && refArr[3] == Data(2), "testAtomicArrayCompareAndSet: FAIL 3")
- assertFailsWith<IndexOutOfBoundsException> {
- refArr.compareAndSet(10, newValue, Data(4))
- }.let { ex ->
- assertEquals("The index 10 is out of the bounds of the AtomicArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- refArr.compareAndSet(-1, newValue, Data(4))
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicArray with size 10.", ex.message)
- }
- }
-
- @Test fun getAndSet() {
- val refArr = AtomicArray<Data?>(10) { null }
- val res4 = refArr.getAndSet(4, Data(1))
- assertEquals(null, res4, "getAndSet: FAIL 1")
- val res5 = refArr.getAndSet(4, Data(2))
- assertEquals(Data(1), res5, "getAndSet: FAIL 2")
- assertFailsWith<IndexOutOfBoundsException> {
- refArr.getAndSet(10, Data(1))
- }.let { ex ->
- assertEquals("The index 10 is out of the bounds of the AtomicArray with size 10.", ex.message)
- }
- assertFailsWith<IndexOutOfBoundsException> {
- refArr.getAndSet(-1, Data(1))
- }.let { ex ->
- assertEquals("The index -1 is out of the bounds of the AtomicArray with size 10.", ex.message)
- }
- }
-}
\ No newline at end of file
diff --git a/kotlin-native/runtime/test/concurrent/AtomicStressTest.kt b/kotlin-native/runtime/test/concurrent/AtomicStressTest.kt
index 64f5b70..bff65d9 100644
--- a/kotlin-native/runtime/test/concurrent/AtomicStressTest.kt
+++ b/kotlin-native/runtime/test/concurrent/AtomicStressTest.kt
@@ -39,24 +39,24 @@
@Test fun addAndGet() {
val atomic = AtomicInt(10)
val futures = ThreadPool.execute {
- atomic.addAndGet(1000)
+ atomic.addAndFetch(1000)
}
futures.forEach {
it.result
}
- assertEquals(10 + 1000 * futures.size, atomic.value)
+ assertEquals(10 + 1000 * futures.size, atomic.load())
}
@Test fun incrementAndGet() {
val initial = 15
val atomic = AtomicInt(initial)
val futures = ThreadPool.execute {
- atomic.incrementAndGet()
+ atomic.incrementAndFetch()
}
futures.forEach {
it.result
}
- assertEquals(initial + futures.size, atomic.value)
+ assertEquals(initial + futures.size, atomic.load())
}
@Test fun mutex() {
@@ -67,7 +67,7 @@
// When it is negative - worker executes exclusively.
val tag = index + 1
while (place.compareAndExchange(tag, -tag) != tag) {}
- assertEquals(index + 1, counter.incrementAndGet())
+ assertEquals(index + 1, counter.incrementAndFetch())
// Now, let the next worker run.
val previousPlace = place.compareAndExchange(-tag, tag + 1)
assertEquals(-tag, previousPlace)
@@ -75,7 +75,7 @@
futures.forEach {
it.result
}
- assertEquals(futures.size, counter.value)
+ assertEquals(futures.size, counter.load())
}
}
@@ -86,12 +86,12 @@
@Test fun addAndGet() {
val atomic = AtomicLong(10L)
val futures = ThreadPool.execute {
- atomic.addAndGet(9999999999)
+ atomic.addAndFetch(9999999999)
}
futures.forEach {
it.result
}
- assertEquals(10L + 9999999999 * futures.size, atomic.value)
+ assertEquals(10L + 9999999999 * futures.size, atomic.load())
}
}
@@ -100,11 +100,11 @@
private class Node<T>(val value: T, val next: Node<T>?)
- fun isEmpty(): Boolean = top.value == null
+ fun isEmpty(): Boolean = top.load() == null
fun push(value: T) {
while(true) {
- val cur = top.value
+ val cur = top.load()
val upd = Node(value, cur)
if (top.compareAndSet(cur, upd)) return
}
@@ -112,7 +112,7 @@
fun pop(): T? {
while(true) {
- val cur = top.value
+ val cur = top.load()
if (cur == null) return null
if (top.compareAndSet(cur, cur.next)) return cur.value
}
@@ -132,7 +132,7 @@
val seen = mutableListOf<Int>()
futures.forEach {
while(true) {
- val current = common.value ?: continue
+ val current = common.load() ?: continue
// Each worker publishes exactly once
assertFalse(seen.contains(current.value))
seen.add(current.value)
@@ -172,16 +172,16 @@
val intArr = AtomicIntArray(10)
val futures = ThreadPool.execute {
for (i in 0 until 500) {
- val index = (0 until intArr.length).random()
- intArr.incrementAndGet(index)
+ val index = (0 until intArr.size).random()
+ intArr.incrementAndFetchAt(index)
}
}
futures.forEach {
it.result
}
var sum = 0
- for (i in 0 until intArr.length) {
- sum += intArr[i]
+ for (i in 0 until intArr.size) {
+ sum += intArr.loadAt(i)
}
assertEquals(futures.size * 500, sum)
}
@@ -195,16 +195,16 @@
val longArr = AtomicLongArray(10)
val futures = ThreadPool.execute {
for (i in 0 until 500) {
- val index = (0 until longArr.length).random()
- longArr.incrementAndGet(index)
+ val index = (0 until longArr.size).random()
+ longArr.incrementAndFetchAt(index)
}
}
futures.forEach {
it.result
}
var sum = 0L
- for (i in 0 until longArr.length) {
- sum += longArr[i]
+ for (i in 0 until longArr.size) {
+ sum += longArr.loadAt(i)
}
assertEquals(futures.size.toLong() * 500, sum)
}
@@ -218,11 +218,11 @@
val refArr = AtomicArray(10) { Data(0) }
val futures = ThreadPool.execute {
for (i in 0 until 500) {
- val index = (0 until refArr.length).random()
+ val index = (0 until refArr.size).random()
while(true) {
- val cur = refArr[index]
+ val cur = refArr.loadAt(index)
val newValue = Data(cur.value + 1)
- if (refArr.compareAndSet(index, cur, newValue)) break
+ if (refArr.compareAndSetAt(index, cur, newValue)) break
}
}
}
@@ -230,8 +230,8 @@
it.result
}
var sum = 0
- for (i in 0 until refArr.length) {
- sum += refArr[i].value
+ for (i in 0 until refArr.size) {
+ sum += refArr.loadAt(i).value
}
assertEquals(futures.size * 500, sum)
}
diff --git a/kotlin-native/runtime/test/concurrent/AtomicTest.kt b/kotlin-native/runtime/test/concurrent/AtomicTest.kt
index 3cf2bcb..dda9713 100644
--- a/kotlin-native/runtime/test/concurrent/AtomicTest.kt
+++ b/kotlin-native/runtime/test/concurrent/AtomicTest.kt
@@ -9,209 +9,20 @@
import kotlin.native.internal.NativePtr
import kotlin.test.*
-data class Data(val value: Int)
-
-class AtomicIntTest {
- @Test fun ctor() {
- val x = AtomicInt(0)
- assertEquals(x.value, 0)
- }
-
- @Test fun setter() {
- val x = AtomicInt(0)
- x.value = 1
- assertEquals(x.value, 1)
- }
-
- @Test fun addAndGet() {
- val x = AtomicInt(1)
- val result = x.addAndGet(2)
- assertEquals(result, 1 + 2)
- assertEquals(x.value, result)
- }
-
- @Test fun compareAndExchange() {
- val x = AtomicInt(0)
- val successValue = x.compareAndExchange(0, 1)
- assertEquals(successValue, 0)
- assertEquals(x.value, 1)
- val failValue = x.compareAndExchange(0, 2)
- assertEquals(failValue, 1)
- assertEquals(x.value, 1)
- }
-
- @Test fun compareAndSet() {
- val x = AtomicInt(0)
- val successValue = x.compareAndSet(0, 1)
- assertTrue(successValue)
- assertEquals(x.value, 1)
- val failValue = x.compareAndSet(0, 2)
- assertFalse(failValue)
- assertEquals(x.value, 1)
- }
-
- @Test fun smoke() {
- val atomic = AtomicInt(3)
- assertEquals(3, atomic.value)
- atomic.value = 5
- assertEquals(5, atomic.value)
- assertEquals(5, atomic.getAndSet(6))
- assertEquals(6, atomic.value)
- assertTrue(atomic.compareAndSet(6, 8))
- assertFalse(atomic.compareAndSet(9, 1))
- assertEquals(8, atomic.value)
- assertEquals(8, atomic.getAndAdd(5))
- assertEquals(13, atomic.value)
- assertEquals(18, atomic.addAndGet(5))
- assertEquals(18, atomic.getAndIncrement())
- assertEquals(19, atomic.value)
- assertEquals(20, atomic.incrementAndGet())
- assertEquals(20, atomic.value)
- assertEquals(20, atomic.getAndDecrement())
- assertEquals(19, atomic.value)
- assertEquals(18, atomic.decrementAndGet())
- assertEquals(18, atomic.value)
- assertEquals(18, atomic.compareAndExchange(18, 56))
- assertEquals(56, atomic.compareAndExchange(18, 56))
- assertEquals(56, atomic.compareAndExchange(18, 56))
- }
-}
-
-class AtomicLongTest {
- @Test fun ctor() {
- val x = AtomicLong(0)
- assertEquals(x.value, 0)
- }
-
- @Test fun setter() {
- val x = AtomicLong(0)
- x.value = 1
- assertEquals(x.value, 1)
- }
-
- @Test fun addAndGet() {
- val x = AtomicLong(1)
- val result = x.addAndGet(2L)
- assertEquals(result, 1 + 2)
- assertEquals(x.value, result)
- }
-
- @Test fun compareAndExchange() {
- val x = AtomicLong(0)
- val successValue = x.compareAndExchange(0, 1)
- assertEquals(successValue, 0)
- assertEquals(x.value, 1)
- val failValue = x.compareAndExchange(0, 2)
- assertEquals(failValue, 1)
- assertEquals(x.value, 1)
- }
-
- @Test fun compareAndSet() {
- val x = AtomicLong(0)
- val successValue = x.compareAndSet(0, 1)
- assertTrue(successValue)
- assertEquals(x.value, 1)
- val failValue = x.compareAndSet(0, 2)
- assertFalse(failValue)
- assertEquals(x.value, 1)
- }
-
- @Test fun smoke() {
- val atomic = AtomicLong(1424920024888900000)
- assertEquals(1424920024888900000, atomic.value)
- atomic.value = 2424920024888900000
- assertEquals(2424920024888900000, atomic.value)
- assertEquals(2424920024888900000, atomic.getAndSet(3424920024888900000))
- assertEquals(3424920024888900000, atomic.value)
- assertTrue(atomic.compareAndSet(3424920024888900000, 4424920024888900000))
- assertFalse(atomic.compareAndSet(9, 1))
- assertEquals(4424920024888900000, atomic.value)
- assertEquals(4424920024888900000, atomic.getAndAdd(100000))
- assertEquals(4424920024889000000, atomic.value)
- assertEquals(4424920024890000000, atomic.addAndGet(1000000L))
- assertEquals(4424920024890000000, atomic.getAndIncrement())
- assertEquals(4424920024890000001, atomic.value)
- assertEquals(4424920024890000002, atomic.incrementAndGet())
- assertEquals(4424920024890000002, atomic.value)
- assertEquals(4424920024890000002, atomic.getAndDecrement())
- assertEquals(4424920024890000001, atomic.value)
- assertEquals(4424920024890000000, atomic.decrementAndGet())
- assertEquals(4424920024890000000, atomic.value)
- assertEquals(4424920024890000000, atomic.compareAndExchange(4424920024890000000, 5424920024890000000))
- assertEquals(5424920024890000000, atomic.compareAndExchange(18, 56))
- assertEquals(5424920024890000000, atomic.compareAndExchange(18, 56))
- }
-}
-
-class AtomicReferenceTest {
- @Test fun ctor() {
- val x = AtomicReference(Data(1))
- assertEquals(x.value, Data(1))
- }
-
- @Test fun setter() {
- val x = AtomicReference<Data>(Data(1))
- x.value = Data(2)
- assertEquals(x.value, 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.value, new)
- val failValue = x.compareAndExchange(initial, Data(3))
- assertEquals(failValue, new)
- assertEquals(x.value, 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.value, new)
- val failValue = x.compareAndSet(initial, Data(2))
- assertFalse(failValue)
- assertEquals(x.value, 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.value)
- atomic.value = listOf(Data(1), Data(2), Data(1))
- assertEquals(listOf(Data(1), Data(2), Data(1)), atomic.value)
- assertEquals(listOf(Data(1), Data(2), Data(1)), atomic.getAndSet(listOf(Data(1), Data(1), Data(1))))
- assertEquals(listOf(Data(1), Data(1), Data(1)), atomic.value)
- var cur = atomic.value
- 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.value)
- cur = atomic.value
- 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))))
- }
-}
-
class AtomicNativePtrTest {
@Test fun smoke() {
val atomic = AtomicNativePtr(NativePtr.NULL)
- assertEquals(NativePtr.NULL, atomic.value)
- atomic.value = NativePtr.NULL.plus(10L)
- assertEquals(10L, atomic.value.toLong())
+ assertEquals(NativePtr.NULL, atomic.load())
+ atomic.store(NativePtr.NULL.plus(10L))
+ assertEquals(10L, atomic.load().toLong())
assertTrue(atomic.compareAndSet(NativePtr.NULL.plus(10L), NativePtr.NULL.plus(20L)))
- assertEquals(20L, atomic.value.toLong())
+ assertEquals(20L, atomic.load().toLong())
assertFalse(atomic.compareAndSet(NativePtr.NULL.plus(10L), NativePtr.NULL.plus(20L)))
- assertEquals(20L, atomic.value.toLong())
+ assertEquals(20L, atomic.load().toLong())
assertEquals(NativePtr.NULL.plus(20L), atomic.compareAndExchange(NativePtr.NULL.plus(20L), NativePtr.NULL.plus(30L)))
assertEquals(NativePtr.NULL.plus(30L), atomic.compareAndExchange(NativePtr.NULL.plus(20L), NativePtr.NULL.plus(40L)))
assertEquals(NativePtr.NULL.plus(30L), atomic.compareAndExchange(NativePtr.NULL.plus(20L), NativePtr.NULL.plus(50L)))
- assertEquals(30L, atomic.getAndSet(NativePtr.NULL.plus(55L)).toLong())
- assertEquals(55L, atomic.value.toLong())
+ assertEquals(30L, atomic.exchange(NativePtr.NULL.plus(55L)).toLong())
+ assertEquals(55L, atomic.load().toLong())
}
}
\ No newline at end of file
diff --git a/kotlin-native/runtime/test/native/concurrent/WorkerBoundReference.kt b/kotlin-native/runtime/test/native/concurrent/WorkerBoundReference.kt
index 2963825..fe1dd68 100644
--- a/kotlin-native/runtime/test/native/concurrent/WorkerBoundReference.kt
+++ b/kotlin-native/runtime/test/native/concurrent/WorkerBoundReference.kt
@@ -91,17 +91,17 @@
val worker = Worker.start()
val future = worker.execute(TransferMode.SAFE, { semaphore }) { semaphore ->
- semaphore.incrementAndGet()
- while (semaphore.value < 2) {
+ semaphore.incrementAndFetch()
+ while (semaphore.load() < 2) {
}
global5.value.a
}
- while (semaphore.value < 1) {
+ while (semaphore.load() < 1) {
}
global5.value.freeze()
- semaphore.incrementAndGet()
+ semaphore.incrementAndFetch()
val value = future.result
assertEquals(3, value)
@@ -116,16 +116,16 @@
val worker = Worker.start()
val future = worker.execute(TransferMode.SAFE, { semaphore }) { semaphore ->
- semaphore.incrementAndGet()
- while (semaphore.value < 2) {
+ semaphore.incrementAndFetch()
+ while (semaphore.load() < 2) {
}
global6
}
- while (semaphore.value < 1) {
+ while (semaphore.load() < 1) {
}
global6.value.a = 4
- semaphore.incrementAndGet()
+ semaphore.incrementAndFetch()
val value = future.result
assertEquals(4, value.value.a)
@@ -228,17 +228,17 @@
val worker = Worker.start()
val future = worker.execute(TransferMode.SAFE, { Pair(local, semaphore) }) { (local, semaphore) ->
- semaphore.incrementAndGet()
- while (semaphore.value < 2) {
+ semaphore.incrementAndFetch()
+ while (semaphore.load() < 2) {
}
local.value.a
}
- while (semaphore.value < 1) {
+ while (semaphore.load() < 1) {
}
local.value.freeze()
- semaphore.incrementAndGet()
+ semaphore.incrementAndFetch()
val value = future.result
assertEquals(3, value)
@@ -280,16 +280,16 @@
val worker = Worker.start()
val future = worker.execute(TransferMode.SAFE, { Pair(local, semaphore) }) { (local, semaphore) ->
- semaphore.incrementAndGet()
- while (semaphore.value < 2) {
+ semaphore.incrementAndFetch()
+ while (semaphore.load() < 2) {
}
local
}
- while (semaphore.value < 1) {
+ while (semaphore.load() < 1) {
}
local.value.a = 4
- semaphore.incrementAndGet()
+ semaphore.incrementAndFetch()
val value = future.result
assertEquals(4, value.value.a)
@@ -395,7 +395,7 @@
ref.value.a
}
}
- workerUnlocker.incrementAndGet()
+ workerUnlocker.incrementAndFetch()
for (future in futures) {
val value = future.result
diff --git a/libraries/stdlib/js/src/kotlin/concurrent/AtomicArrays.js.kt b/libraries/stdlib/js/src/kotlin/concurrent/AtomicArrays.js.kt
new file mode 100644
index 0000000..780b0f0
--- /dev/null
+++ b/libraries/stdlib/js/src/kotlin/concurrent/AtomicArrays.js.kt
@@ -0,0 +1,438 @@
+/*
+ * 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.
+ */
+
+package kotlin.concurrent
+
+/**
+ * An array of ints which provides API of the common [AtomicIntArray].
+ *
+ * Does not provide any atomicity guarantees since the JS platform does not support multi-threading.
+ */
+public actual class AtomicIntArray {
+ private val array: IntArray
+
+ /**
+ * Creates a new [AtomicIntArray] of the given [size], with all elements initialized to zero.
+ *
+ * @throws RuntimeException if the specified [size] is negative.
+ */
+ public actual constructor(size: Int) {
+ array = IntArray(size)
+ }
+
+ /**
+ * Creates a new [AtomicIntArray] filled with elements of the given [array].
+ */
+ public actual constructor(array: IntArray) {
+ this.array = array.copyOf()
+ }
+
+ /**
+ * Returns the number of elements in the array.
+ */
+ public actual val size: Int get() = array.size
+
+ /**
+ * Gets the value of the element at the given [index].
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun loadAt(index: Int): Int {
+ checkBounds(index)
+ return array[index]
+ }
+
+ /**
+ * Sets the value of the element at the given [index] to the [new value][newValue].
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun storeAt(index: Int, newValue: Int) {
+ checkBounds(index)
+ array[index] = newValue
+ }
+
+ /**
+ * Sets the value of the element at the given [index] to the [new value][newValue]
+ * and returns the old value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun exchangeAt(index: Int, newValue: Int): Int {
+ checkBounds(index)
+ val oldValue = array[index]
+ array[index] = newValue
+ return oldValue
+ }
+
+ /**
+ * Sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue].
+ * Returns true if the operation was successful and false only if the current value of the element was not equal to the expected value.
+ *
+ * Comparison of values is done by value.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun compareAndSetAt(index: Int, expectedValue: Int, newValue: Int): Boolean {
+ checkBounds(index)
+ if (array[index] != expectedValue) return false
+ array[index] = newValue
+ return true
+ }
+
+ /**
+ * Sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue] and returns the old value of the element in any case.
+ *
+ * Comparison of values is done by value.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun compareAndExchangeAt(index: Int, expectedValue: Int, newValue: Int): Int {
+ checkBounds(index)
+ val oldValue = array[index]
+ if (oldValue == expectedValue) {
+ array[index] = newValue
+ }
+ return oldValue
+ }
+
+ /**
+ * Adds the given [delta] to the element at the given [index] and returns the old value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun fetchAndAddAt(index: Int, delta: Int): Int {
+ checkBounds(index)
+ val oldValue = array[index]
+ array[index] += delta
+ return oldValue
+ }
+
+ /**
+ * Adds the given [delta] to the element at the given [index] and returns the new value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun addAndFetchAt(index: Int, delta: Int): Int {
+ checkBounds(index)
+ array[index] += delta
+ return array[index]
+ }
+
+ /**
+ * Increments the element at the given [index] by one and returns the old value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun fetchAndIncrementAt(index: Int): Int {
+ checkBounds(index)
+ return array[index]++
+ }
+
+ /**
+ * Increments the element at the given [index] by one and returns the new value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun incrementAndFetchAt(index: Int): Int {
+ checkBounds(index)
+ return ++array[index]
+ }
+
+ /**
+ * Decrements the element at the given [index] by one and returns the old value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun fetchAndDecrementAt(index: Int): Int {
+ checkBounds(index)
+ return array[index]--
+ }
+
+ /**
+ * Decrements the element at the given [index] by one and returns the new value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun decrementAndFetchAt(index: Int): Int {
+ checkBounds(index)
+ return --array[index]
+ }
+
+ /**
+ * Returns the string representation of the underlying array of ints.
+ */
+ public actual override fun toString(): String = array.toString()
+
+ private fun checkBounds(index: Int) {
+ if (index < 0 || index >= array.size) throw IndexOutOfBoundsException("index $index")
+ }
+}
+
+/**
+ * An array of longs which provides API of the common [AtomicLongArray].
+ *
+ * Does not provide any atomicity guarantees since the JS platform does not support multi-threading.
+ */
+public actual class AtomicLongArray {
+ private val array: LongArray
+
+ /**
+ * Creates a new [AtomicLongArray] of the given [size], with all elements initialized to zero.
+ *
+ * @throws RuntimeException if the specified [size] is negative.
+ */
+ public actual constructor(size: Int) {
+ array = LongArray(size)
+ }
+
+ /**
+ * Creates a new [AtomicIntArray] filled with elements of the given [array].
+ */
+ public actual constructor(array: LongArray) {
+ this.array = array.copyOf()
+ }
+
+ /**
+ * Returns the number of elements in the array.
+ */
+ public actual val size: Int get() = array.size
+
+ /**
+ * Gets the value of the element at the given [index].
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun loadAt(index: Int): Long {
+ checkBounds(index)
+ return array[index]
+ }
+
+ /**
+ * Sets the value of the element at the given [index] to the [new value][newValue].
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun storeAt(index: Int, newValue: Long) {
+ checkBounds(index)
+ array[index] = newValue
+ }
+
+ /**
+ * Sets the value of the element at the given [index] to the [new value][newValue]
+ * and returns the old value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun exchangeAt(index: Int, newValue: Long): Long {
+ checkBounds(index)
+ val oldValue = array[index]
+ array[index] = newValue
+ return oldValue
+ }
+
+ /**
+ * Sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue].
+ * Returns true if the operation was successful and false only if the current value of the element was not equal to the expected value.
+ *
+ * Comparison of values is done by value.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun compareAndSetAt(index: Int, expectedValue: Long, newValue: Long): Boolean {
+ checkBounds(index)
+ if (array[index] != expectedValue) return false
+ array[index] = newValue
+ return true
+ }
+
+ /**
+ * Sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue] and returns the old value of the element in any case.
+ *
+ * Comparison of values is done by value.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun compareAndExchangeAt(index: Int, expectedValue: Long, newValue: Long): Long {
+ checkBounds(index)
+ val oldValue = array[index]
+ if (oldValue == expectedValue) {
+ array[index] = newValue
+ }
+ return oldValue
+ }
+
+ /**
+ * Adds the given [delta] to the element at the given [index] and returns the old value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun fetchAndAddAt(index: Int, delta: Long): Long {
+ checkBounds(index)
+ val oldValue = array[index]
+ array[index] += delta
+ return oldValue
+ }
+
+ /**
+ * Adds the given [delta] to the element at the given [index] and returns the new value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun addAndFetchAt(index: Int, delta: Long): Long {
+ checkBounds(index)
+ array[index] += delta
+ return array[index]
+ }
+
+ /**
+ * Increments the element at the given [index] by one and returns the old value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun fetchAndIncrementAt(index: Int): Long {
+ checkBounds(index)
+ return array[index]++
+ }
+
+ /**
+ * Increments the element at the given [index] by one and returns the new value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun incrementAndFetchAt(index: Int): Long {
+ checkBounds(index)
+ return ++array[index]
+ }
+
+ /**
+ * Decrements the element at the given [index] by one and returns the old value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun fetchAndDecrementAt(index: Int): Long {
+ checkBounds(index)
+ return array[index]--
+ }
+
+ /**
+ * Decrements the element at the given [index] by one and returns the new value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun decrementAndFetchAt(index: Int): Long {
+ checkBounds(index)
+ return --array[index]
+ }
+
+ /**
+ * Returns the string representation of the underlying array of longs.
+ */
+ public actual override fun toString(): String = array.toString()
+
+ private fun checkBounds(index: Int) {
+ if (index < 0 || index >= array.size) throw IndexOutOfBoundsException("index $index")
+ }
+}
+
+/**
+ * An array of longs which provides API of the common [AtomicArray].
+ *
+ * Does not provide any atomicity guarantees since the JS platform does not support multi-threading.
+ */
+public actual class AtomicArray<T> {
+ private val array: Array<T>
+
+ /**
+ * Creates a new [AtomicArray] filled with elements of the given [array].
+ */
+ public actual constructor (array: Array<T>) {
+ this.array = array.copyOf()
+ }
+
+ /**
+ * Returns the number of elements in the array.
+ */
+ public actual val size: Int get() = array.size
+
+ /**
+ * Gets the value of the element at the given [index].
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun loadAt(index: Int): T {
+ checkBounds(index)
+ return array[index]
+ }
+
+ /**
+ * Sets the value of the element at the given [index] to the [new value][newValue].
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun storeAt(index: Int, newValue: T) {
+ checkBounds(index)
+ array[index] = newValue
+ }
+
+ /**
+ * Sets the value of the element at the given [index] to the [new value][newValue]
+ * and returns the old value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun exchangeAt(index: Int, newValue: T): T {
+ checkBounds(index)
+ val oldValue = array[index]
+ array[index] = newValue
+ return oldValue
+ }
+
+ /**
+ * Sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue].
+ * Returns true if the operation was successful and false only if the current value of the element was not equal to the expected value.
+ *
+ * Comparison of values is done by value.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun compareAndSetAt(index: Int, expectedValue: T, newValue: T): Boolean {
+ checkBounds(index)
+ if (array[index] != expectedValue) return false
+ array[index] = newValue
+ return true
+ }
+
+ /**
+ * Sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue] and returns the old value of the element in any case.
+ *
+ * Comparison of values is done by value.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun compareAndExchangeAt(index: Int, expectedValue: T, newValue: T): T {
+ checkBounds(index)
+ val oldValue = array[index]
+ if (oldValue == expectedValue) {
+ array[index] = newValue
+ }
+ return oldValue
+ }
+
+ /**
+ * Returns the string representation of the underlying array of objects.
+ */
+ public actual override fun toString(): String = array.toString()
+
+ private fun checkBounds(index: Int) {
+ if (index < 0 || index >= array.size) throw IndexOutOfBoundsException("index $index")
+ }
+}
diff --git a/libraries/stdlib/js/src/kotlin/concurrent/Atomics.js.kt b/libraries/stdlib/js/src/kotlin/concurrent/Atomics.js.kt
new file mode 100644
index 0000000..7bf09e5
--- /dev/null
+++ b/libraries/stdlib/js/src/kotlin/concurrent/Atomics.js.kt
@@ -0,0 +1,310 @@
+/*
+ * 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.
+ */
+
+package kotlin.concurrent
+
+/**
+ * An [Int] value which provides API of the common [AtomicInt].
+ *
+ * Does not provide any atomicity guarantees since the JS platform does not support multi-threading.
+ */
+public actual class AtomicInt public actual constructor(private var value: Int) {
+
+ /**
+ * Gets the value of the atomic.
+ */
+ public actual fun load(): Int = value
+
+ /**
+ * Sets the value of the atomic to the [new value][newValue].
+ */
+ public actual fun store(newValue: Int) { value = newValue }
+
+ /**
+ * Sets the value to the given [new value][newValue] and returns the old value.
+ */
+ public actual fun exchange(newValue: Int): Int {
+ val oldValue = value
+ value = newValue
+ return oldValue
+ }
+
+ /**
+ * Sets the value to the given [new value][newValue] if the current value equals the [expected value][expectedValue],
+ * returns true if the operation was successful and false only if the current value was not equal to the expected value.
+ *
+ * Comparison of values is done by value.
+ */
+ public actual fun compareAndSet(expectedValue: Int, newValue: Int): Boolean {
+ if (value != expectedValue) return false
+ value = newValue
+ return true
+ }
+
+ /**
+ * Sets the value to the given [new value][newValue] if the current value equals the [expected value][expected]
+ * and returns the old value in any case.
+ *
+ * Comparison of values is done by value.
+ */
+ public actual fun compareAndExchange(expected: Int, newValue: Int): Int {
+ val oldValue = value
+ if (oldValue == expected) {
+ value = newValue
+ }
+ return oldValue
+ }
+
+ /**
+ * Adds the [given value][delta] to the current value and returns the old value.
+ */
+ public actual fun fetchAndAdd(delta: Int): Int {
+ val oldValue = value
+ value += delta
+ return oldValue
+ }
+
+ /**
+ * Adds the [given value][delta] to the current value and returns the new value.
+ */
+ public actual fun addAndFetch(delta: Int): Int {
+ value += delta
+ return value
+ }
+
+ /**
+ * Increments the current value by one and returns the old value.
+ */
+ public actual fun fetchAndIncrement(): Int = value++
+
+ /**
+ * Increments the current value by one and returns the new value.
+ */
+ public actual fun incrementAndFetch(): Int = ++value
+
+ /**
+ * Decrements the current value by one and returns the new value.
+ */
+ public actual fun fetchAndDecrement(): Int = value--
+
+ /**
+ * Decrements the current value by one and returns the old value.
+ */
+ public actual fun decrementAndFetch(): Int = --value
+
+ /**
+ * Returns the string representation of the underlying [Int] value.
+ */
+ public actual override fun toString(): String = value.toString()
+}
+
+/**
+ * An [Long] value which provides API of the common [AtomicLong].
+ *
+ * Does not provide any atomicity guarantees since the JS platform does not support multi-threading.
+ */
+public actual class AtomicLong public actual constructor(private var value: Long) {
+ /**
+ * Gets the value of the atomic.
+ */
+ public actual fun load(): Long = value
+
+ /**
+ * Sets the value of the atomic to the [new value][newValue].
+ */
+ public actual fun store(newValue: Long) { value = newValue }
+
+ /**
+ * Sets the value to the given [new value][newValue] and returns the old value.
+ */
+ public actual fun exchange(newValue: Long): Long {
+ val oldValue = value
+ value = newValue
+ return oldValue
+ }
+
+ /**
+ * Sets the value to the given [new value][newValue] if the current value equals the [expected value][expectedValue],
+ * returns true if the operation was successful and false only if the current value was not equal to the expected value.
+ *
+ * Comparison of values is done by value.
+ */
+ public actual fun compareAndSet(expected: Long, newValue: Long): Boolean {
+ if (value != expected) return false
+ value = newValue
+ return true
+ }
+
+ /**
+ * Sets the value to the given [new value][newValue] if the current value equals the [expected value][expected]
+ * and returns the old value in any case.
+ *
+ * Comparison of values is done by value.
+ */
+ public actual fun compareAndExchange(expected: Long, newValue: Long): Long {
+ val oldValue = value
+ if (oldValue == expected) {
+ value = newValue
+ }
+ return oldValue
+ }
+
+ /**
+ * Adds the [given value][delta] to the current value and returns the old value.
+ */
+ public actual fun fetchAndAdd(delta: Long): Long {
+ val oldValue = value
+ value += delta
+ return oldValue
+ }
+
+ /**
+ * Adds the [given value][delta] to the current value and returns the new value.
+ */
+ public actual fun addAndFetch(delta: Long): Long {
+ value += delta
+ return value
+ }
+
+ /**
+ * Increments the current value by one and returns the old value.
+ */
+ public actual fun fetchAndIncrement(): Long = value++
+
+ /**
+ * Increments the current value by one and returns the new value.
+ */
+ public actual fun incrementAndFetch(): Long = ++value
+
+ /**
+ * Decrements the current value by one and returns the new value.
+ */
+ public actual fun fetchAndDecrement(): Long = value--
+
+ /**
+ * Decrements the current value by one and returns the old value.
+ */
+ public actual fun decrementAndFetch(): Long = --value
+
+ /**
+ * Returns the string representation of the underlying [Long] value.
+ */
+ public actual override fun toString(): String = value.toString()
+}
+
+/**
+ * An [Boolean] value which provides API of the common [AtomicBoolean].
+ *
+ * Does not provide any atomicity guarantees since the JS platform does not support multi-threading.
+ */
+public actual class AtomicBoolean public actual constructor(private var value: Boolean) {
+
+ /**
+ * Gets the value of the atomic.
+ */
+ public actual fun load(): Boolean = value
+
+ /**
+ * Sets the value of the atomic to the [new value][newValue].
+ */
+ public actual fun store(newValue: Boolean) { value = newValue }
+
+ /**
+ * Sets the value to the given [new value][newValue] and returns the old value.
+ */
+ public actual fun exchange(newValue: Boolean): Boolean {
+ val oldValue = value
+ value = newValue
+ return oldValue
+ }
+
+ /**
+ * Sets the value to the given [new value][newValue] if the current value equals the [expected value][expectedValue],
+ * returns true if the operation was successful and false only if the current value was not equal to the expected value.
+ *
+ * Comparison of values is done by value.
+ */
+ public actual fun compareAndSet(expected: Boolean, newValue: Boolean): Boolean {
+ if (value != expected) return false
+ value = newValue
+ return true
+ }
+
+ /**
+ * Sets the value to the given [new value][newValue] if the current value equals the [expected value][expected]
+ * and returns the old value in any case.
+ *
+ * Comparison of values is done by value.
+ */
+ public actual fun compareAndExchange(expected: Boolean, newValue: Boolean): Boolean {
+ val oldValue = value
+ if (oldValue == expected) {
+ value = newValue
+ }
+ return oldValue
+ }
+
+ /**
+ * Returns the string representation of the underlying [Boolean] value.
+ */
+ public actual override fun toString(): String = value.toString()
+}
+
+/**
+ * An object reference which provides API of the common [AtomicReference].
+ *
+ * Does not provide any atomicity guarantees since the JS platform does not support multi-threading.
+ */
+public actual class AtomicReference<T> public actual constructor(private var value: T) {
+ /**
+ * Gets the value of the atomic.
+ */
+ public actual fun load(): T = value
+
+ /**
+ * Sets the value of the atomic to the [new value][newValue].
+ */
+ public actual fun store(newValue: T) { value = newValue }
+
+ /**
+ * Sets the value to the given [new value][newValue] and returns the old value.
+ */
+ public actual fun exchange(newValue: T): T {
+ val oldValue = value
+ value = newValue
+ return oldValue
+ }
+
+ /**
+ * Sets the value to the given [new value][newValue] if the current value equals the [expected value][expectedValue],
+ * returns true if the operation was successful and false only if the current value was not equal to the expected value.
+ *
+ * Comparison of values is done by value.
+ */
+ public actual fun compareAndSet(expected: T, newValue: T): Boolean {
+ if (value != expected) return false
+ value = newValue
+ return true
+ }
+
+ /**
+ * Sets the value to the given [new value][newValue] if the current value equals the [expected value][expected]
+ * and returns the old value in any case.
+ *
+ * Comparison of values is done by value.
+ */
+ public actual fun compareAndExchange(expected: T, newValue: T): T {
+ val oldValue = value
+ if (oldValue == expected) {
+ value = newValue
+ }
+ return oldValue
+ }
+
+ /**
+ * Returns the string representation of the underlying object.
+ */
+ public actual override fun toString(): String = value.toString()
+}
diff --git a/libraries/stdlib/jvm/src/kotlin/concurrent/AtomicArrays.jvm.kt b/libraries/stdlib/jvm/src/kotlin/concurrent/AtomicArrays.jvm.kt
new file mode 100644
index 0000000..0e662d8
--- /dev/null
+++ b/libraries/stdlib/jvm/src/kotlin/concurrent/AtomicArrays.jvm.kt
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+package kotlin.concurrent
+
+import java.util.concurrent.atomic.*
+
+/**
+ * Casts the given [AtomicIntArray] instance to [java.util.concurrent.atomic.AtomicIntegerArray].
+ */
+@Suppress("UNCHECKED_CAST")
+public fun AtomicIntArray.asJavaAtomicArray(): AtomicIntegerArray = this as AtomicIntegerArray
+
+/**
+ * Casts the given [java.util.concurrent.atomic.AtomicIntegerArray] instance to [AtomicIntArray].
+ */
+@Suppress("UNCHECKED_CAST")
+public fun AtomicIntegerArray.asKotlinAtomicArray(): AtomicIntArray = this as AtomicIntArray
+
+/**
+ * Casts the given [AtomicLongArray] instance to [java.util.concurrent.atomic.AtomicLongArray].
+ */
+@Suppress("UNCHECKED_CAST")
+public fun AtomicLongArray.asJavaAtomicArray(): java.util.concurrent.atomic.AtomicLongArray = this as java.util.concurrent.atomic.AtomicLongArray
+
+/**
+ * Casts the given [java.util.concurrent.atomic.AtomicLongArray] instance to [AtomicLongArray].
+ */
+@Suppress("UNCHECKED_CAST")
+public fun java.util.concurrent.atomic.AtomicLongArray.asKotlinAtomicArray(): AtomicLongArray = this as AtomicLongArray
+
+/**
+ * Casts the given [AtomicArray]<T> instance to [java.util.concurrent.atomic.AtomicReferenceArray]<T>.
+ */
+@Suppress("UNCHECKED_CAST")
+public fun <T> AtomicArray<T>.asJavaAtomicArray(): AtomicReferenceArray<T> = this as AtomicReferenceArray<T>
+
+/**
+ * Casts the given [java.util.concurrent.atomic.AtomicReferenceArray]<T> instance to [AtomicArray]<T>.
+ */
+@Suppress("UNCHECKED_CAST")
+public fun <T> AtomicReferenceArray<T>.asKotlinAtomicArray(): AtomicArray<T> = this as AtomicArray<T>
\ No newline at end of file
diff --git a/libraries/stdlib/jvm/src/kotlin/concurrent/Atomics.jvm.kt b/libraries/stdlib/jvm/src/kotlin/concurrent/Atomics.jvm.kt
new file mode 100644
index 0000000..fa6d527
--- /dev/null
+++ b/libraries/stdlib/jvm/src/kotlin/concurrent/Atomics.jvm.kt
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+package kotlin.concurrent
+
+import java.util.concurrent.atomic.*
+
+/**
+ * Casts the given [AtomicInt] instance to [java.util.concurrent.atomic.AtomicInteger].
+ */
+@Suppress("UNCHECKED_CAST")
+public fun AtomicInt.asJavaAtomic(): AtomicInteger = this as AtomicInteger
+
+/**
+ * Casts the given [java.util.concurrent.atomic.AtomicInteger] instance to [AtomicInt].
+ */
+@Suppress("UNCHECKED_CAST")
+public fun AtomicInteger.asKotlinAtomic(): AtomicInt = this as AtomicInt
+
+/**
+ * Casts the given [AtomicLong] instance to [java.util.concurrent.atomic.AtomicLong].
+ */
+@Suppress("UNCHECKED_CAST")
+public fun AtomicLong.asJavaAtomic(): java.util.concurrent.atomic.AtomicLong = this as java.util.concurrent.atomic.AtomicLong
+
+/**
+ * Casts the given [java.util.concurrent.atomic.AtomicLong] instance to [AtomicLong].
+ */
+@Suppress("UNCHECKED_CAST")
+public fun java.util.concurrent.atomic.AtomicLong.asKotlinAtomic(): AtomicLong = this as AtomicLong
+
+/**
+ * Casts the given [AtomicBoolean] instance to [java.util.concurrent.atomic.AtomicBoolean].
+ */
+@Suppress("UNCHECKED_CAST")
+public fun <T> AtomicBoolean.asJavaAtomic(): java.util.concurrent.atomic.AtomicBoolean = this as java.util.concurrent.atomic.AtomicBoolean
+
+/**
+ * Casts the given [java.util.concurrent.atomic.AtomicBoolean] instance to [AtomicBoolean].
+ */
+@Suppress("UNCHECKED_CAST")
+public fun <T> java.util.concurrent.atomic.AtomicBoolean.asKotlinAtomic(): AtomicBoolean = this as AtomicBoolean
+
+/**
+ * Casts the given [AtomicReference]<T> instance to [java.util.concurrent.atomic.AtomicReference]<T>.
+ */
+@Suppress("UNCHECKED_CAST")
+public fun <T> AtomicReference<T>.asJavaAtomic(): java.util.concurrent.atomic.AtomicReference<T> = this as java.util.concurrent.atomic.AtomicReference<T>
+
+/**
+ * Casts the given [java.util.concurrent.atomic.AtomicReference]<T> instance to [AtomicReference]<T>.
+ */
+@Suppress("UNCHECKED_CAST")
+public fun <T> java.util.concurrent.atomic.AtomicReference<T>.asKotlinAtomic(): AtomicReference<T> = this as AtomicReference<T>
\ No newline at end of file
diff --git a/libraries/stdlib/native-wasm/src/kotlin/atomics.kt b/libraries/stdlib/native-wasm/src/kotlin/atomics.kt
deleted file mode 100644
index 12a740a..0000000
--- a/libraries/stdlib/native-wasm/src/kotlin/atomics.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * 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.
- */
-
-package kotlin.concurrent
-
-internal expect class AtomicReference<T>(value: T) {
- public var value: T
- public fun compareAndExchange(expected: T, newValue: T): T
- public fun compareAndSet(expected: T, newValue: T): Boolean
-}
diff --git a/libraries/stdlib/native-wasm/src/kotlin/text/regex/AbstractCharClass.kt b/libraries/stdlib/native-wasm/src/kotlin/text/regex/AbstractCharClass.kt
index 8ca2505..f6a2236 100644
--- a/libraries/stdlib/native-wasm/src/kotlin/text/regex/AbstractCharClass.kt
+++ b/libraries/stdlib/native-wasm/src/kotlin/text/regex/AbstractCharClass.kt
@@ -21,6 +21,7 @@
*/
@file:Suppress("DEPRECATION") // Char.toInt()
+@file:OptIn(ExperimentalStdlibApi::class)
package kotlin.text.regex
import kotlin.experimental.ExperimentalNativeApi
@@ -110,7 +111,7 @@
* The two nodes are then combined in [CompositeRangeSet] node to fully represent this char class.
*/
fun classWithSurrogates(): AbstractCharClass {
- surrogates_.value?.let {
+ surrogates_.load()?.let {
return it
}
val surrogates = lowHighSurrogates
@@ -129,7 +130,7 @@
result.altSurrogates = this.altSurrogates
result.mayContainSupplCodepoints = this.mayContainSupplCodepoints
surrogates_.compareAndSet(null, result)
- return surrogates_.value!!
+ return surrogates_.load()!!
}
@@ -650,9 +651,9 @@
fun getPredefinedClass(name: String, negative: Boolean): AbstractCharClass {
val charClass = classCacheMap[name] ?: throw PatternSyntaxException("No such character class")
- val cachedClass = classCache[charClass.ordinal].value ?: run {
- classCache[charClass.ordinal].compareAndExchange(null, charClass.factory())
- classCache[charClass.ordinal].value!!
+ val cachedClass = classCache[charClass.ordinal].load() ?: run {
+ classCache[charClass.ordinal].compareAndSet(null, charClass.factory())
+ classCache[charClass.ordinal].load()!!
}
return cachedClass.getValue(negative)
}
diff --git a/libraries/stdlib/src/kotlin/concurrent/AtomicArrays.common.kt b/libraries/stdlib/src/kotlin/concurrent/AtomicArrays.common.kt
new file mode 100644
index 0000000..5cf9c9e
--- /dev/null
+++ b/libraries/stdlib/src/kotlin/concurrent/AtomicArrays.common.kt
@@ -0,0 +1,439 @@
+/*
+ * 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.
+ */
+
+package kotlin.concurrent
+
+import kotlin.internal.ActualizeByJvmBuiltinProvider
+
+/**
+ * An array of ints in which elements may be updated atomically with guaranteed sequential consistent ordering.
+ *
+ * Platform-specific implementation details:
+ *
+ * When targeting the Native backend, [AtomicIntArray] stores an [IntArray] and atomically updates it's elements.
+ * For additional details about atomicity guarantees for reads and writes see [kotlin.concurrent.Volatile].
+ *
+ * When targeting the JVM, instances of [AtomicIntArray] are represented by [java.util.concurrent.atomic.AtomicIntegerArray].
+ * For details about guarantees of volatile accesses and updates of atomics refer to The Java Language Specification (17.4 Memory Model).
+ *
+ * For JS and WASM [AtomicIntArray] is implemented trivially and is not thread-safe since these platforms do not support multi-threading.
+ */
+@ActualizeByJvmBuiltinProvider
+public expect class AtomicIntArray {
+ /**
+ * Creates a new [AtomicIntArray] of the specified [size], with all elements initialized to zero.
+ * @throws RuntimeException if the specified [size] is negative.
+ */
+ public constructor(size: Int)
+
+ /**
+ * Creates a new [AtomicIntArray] filled with elements of the given [array].
+ */
+ public constructor(array: IntArray)
+
+ /**
+ * Returns the number of elements in the array.
+ */
+ public val size: Int
+
+ /**
+ * Atomically gets the value of the element at the given [index].
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun loadAt(index: Int): Int
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue].
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun storeAt(index: Int, newValue: Int)
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun exchangeAt(index: Int, newValue: Int): Int
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue].
+ * Returns true if the operation was successful and false only if the current value of the element was not equal to the expected value.
+ *
+ * Provides sequential consistent ordering guarantees and never fails spuriously.
+ *
+ * Comparison of values is done by value.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun compareAndSetAt(index: Int, expectedValue: Int, newValue: Int): Boolean
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue] and returns the old value of the element in any case.
+ *
+ * Provides sequential consistent ordering guarantees and never fails spuriously.
+ *
+ * Comparison of values is done by value.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun compareAndExchangeAt(index: Int, expectedValue: Int, newValue: Int): Int
+
+ /**
+ * Atomically adds the given [delta] to the element at the given [index] and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun fetchAndAddAt(index: Int, delta: Int): Int
+
+ /**
+ * Atomically adds the given [delta] to the element at the given [index] and returns the new value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun addAndFetchAt(index: Int, delta: Int): Int
+
+ /**
+ * Atomically increments the element at the given [index] by one and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun fetchAndIncrementAt(index: Int): Int
+
+ /**
+ * Atomically increments the element at the given [index] by one and returns the new value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun incrementAndFetchAt(index: Int): Int
+
+ /**
+ * Atomically decrements the element at the given [index] by one and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun fetchAndDecrementAt(index: Int): Int
+
+ /**
+ * Atomically decrements the element at the given [index] by one and returns the new value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun decrementAndFetchAt(index: Int): Int
+
+ /**
+ * Returns the string representation of the underlying array of ints.
+ *
+ * This operation does not provide any atomicity guarantees.
+ */
+ public override fun toString(): String
+}
+
+/**
+ * Creates a new [AtomicIntArray] of the given [size], where each element is initialized by calling the given [init] function.
+ *
+ * The function [init] is called for each array element sequentially starting from the first one.
+ * It should return the value for an array element given its index.
+ *
+ * @throws RuntimeException if the specified [size] is negative.
+ */
+@ExperimentalStdlibApi
+public inline fun AtomicIntArray(size: Int, init: (Int) -> Int): AtomicIntArray {
+ val inner = IntArray(size)
+ for (index in 0 until size) {
+ inner[index] = init(index)
+ }
+ return AtomicIntArray(inner)
+}
+
+/**
+ * An array of longs in which elements may be updated atomically with guaranteed sequential consistent ordering.
+ *
+ * Platform-specific implementation details:
+ *
+ * When targeting the Native backend, [AtomicLongArray] stores a [LongArray] and atomically updates it's elements.
+ * For additional details about atomicity guarantees for reads and writes see [kotlin.concurrent.Volatile].
+ *
+ * When targeting the JVM, instances of [AtomicLongArray] are represented by [java.util.concurrent.atomic.AtomicLongArray].
+ * For details about guarantees of volatile accesses and updates of atomics refer to The Java Language Specification (17.4 Memory Model).
+ *
+ * For JS and WASM [AtomicLongArray] is implemented trivially and is not thread-safe since these platforms do not support multi-threading.
+ */
+@ActualizeByJvmBuiltinProvider
+public expect class AtomicLongArray {
+ /**
+ * Creates a new [AtomicLongArray] of the specified [size], with all elements initialized to zero.
+ * @throws RuntimeException if the specified [size] is negative.
+ */
+ public constructor(size: Int)
+
+ /**
+ * Creates a new [AtomicLongArray] filled with elements of the given [array].
+ */
+ public constructor(array: LongArray)
+
+ /**
+ * Returns the number of elements in the array.
+ */
+ public val size: Int
+
+ /**
+ * Atomically gets the value of the element at the given [index].
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun loadAt(index: Int): Long
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue].
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun storeAt(index: Int, newValue: Long)
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun exchangeAt(index: Int, newValue: Long): Long
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue].
+ * Returns true if the operation was successful and false only if the current value of the element was not equal to the expected value.
+ *
+ * Provides sequential consistent ordering guarantees and never fails spuriously.
+ *
+ * Comparison of values is done by value.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun compareAndSetAt(index: Int, expectedValue: Long, newValue: Long): Boolean
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue] and returns the old value of the element in any case.
+ *
+ * Provides sequential consistent ordering guarantees and never fails spuriously.
+ *
+ * Comparison of values is done by value.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun compareAndExchangeAt(index: Int, expectedValue: Long, newValue: Long): Long
+
+ /**
+ * Atomically adds the given [delta] to the element at the given [index] and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun fetchAndAddAt(index: Int, delta: Long): Long
+
+ /**
+ * Atomically adds the given [delta] to the element at the given [index] and returns the new value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun addAndFetchAt(index: Int, delta: Long): Long
+
+ /**
+ * Atomically increments the element at the given [index] by one and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun fetchAndIncrementAt(index: Int): Long
+
+ /**
+ * Atomically increments the element at the given [index] by one and returns the new value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun incrementAndFetchAt(index: Int): Long
+
+ /**
+ * Atomically decrements the element at the given [index] by one and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun fetchAndDecrementAt(index: Int): Long
+
+ /**
+ * Atomically decrements the element at the given [index] by one and returns the new value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun decrementAndFetchAt(index: Int): Long
+
+ /**
+ * Returns the string representation of the underlying array of longs.
+ *
+ * This operation does not provide any atomicity guarantees.
+ */
+ public override fun toString(): String
+}
+
+/**
+ * Creates a new [AtomicLongArray] of the given [size], where each element is initialized by calling the given [init] function.
+ *
+ * The function [init] is called for each array element sequentially starting from the first one.
+ * It should return the value for an array element given its index.
+ *
+ * @throws RuntimeException if the specified [size] is negative.
+ */
+@ExperimentalStdlibApi
+public inline fun AtomicLongArray(size: Int, init: (Int) -> Long): AtomicLongArray {
+ val inner = LongArray(size)
+ for (index in 0 until size) {
+ inner[index] = init(index)
+ }
+ return AtomicLongArray(inner)
+}
+
+/**
+ * A generic array of objects in which elements may be updated atomically with guaranteed sequential consistent ordering.
+ *
+ * Platform-specific implementation details:
+ *
+ * When targeting the Native backend, [AtomicArray] stores an [Array] with elements of type [T] and atomically updates it's elements.
+ * For additional details about atomicity guarantees for reads and writes see [kotlin.concurrent.Volatile].
+ *
+ * When targeting the JVM, instances of [AtomicArray] are represented by [java.util.concurrent.atomic.AtomicReferenceArray].
+ * For details about guarantees of volatile accesses and updates of atomics refer to The Java Language Specification (17.4 Memory Model).
+ *
+ * For JS and WASM [AtomicArray] is implemented trivially and is not thread-safe since these platforms do not support multi-threading.
+ */
+@ActualizeByJvmBuiltinProvider
+public expect class AtomicArray<T> {
+
+ /**
+ * Creates a new [AtomicArray]<T> filled with elements of the given [array].
+ */
+ public constructor(array: Array<T>)
+
+ /**
+ * Returns the number of elements in the array.
+ */
+ public val size: Int
+
+ /**
+ * Atomically gets the value of the element at the given [index].
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun loadAt(index: Int): T
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue].
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun storeAt(index: Int, newValue: T)
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * and returns the old value of the element.
+ *
+ * Provides sequential consistent ordering guarantees.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun exchangeAt(index: Int, newValue: T): T
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue].
+ * Returns true if the operation was successful and false only if the current value of the element was not equal to the expected value.
+ *
+ * Provides sequential consistent ordering guarantees and never fails spuriously.
+ *
+ * Comparison of values is done by reference.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun compareAndSetAt(index: Int, expectedValue: T, newValue: T): Boolean
+
+ /**
+ * Atomically sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue] and returns the old value of the element in any case.
+ *
+ * Provides sequential consistent ordering guarantees and never fails spuriously.
+ *
+ * Comparison of values is done by reference.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public fun compareAndExchangeAt(index: Int, expectedValue: T, newValue: T): T
+
+ /**
+ * Returns the string representation of the underlying array of objects.
+ *
+ * This operation does not provide any atomicity guarantees.
+ */
+ public override fun toString(): String
+}
+
+/**
+ * Creates a new [AtomicArray]<T> of the given [size], where each element is initialized by calling the given [init] function.
+ *
+ * The function [init] is called for each array element sequentially starting from the first one.
+ * It should return the value for an array element given its index.
+ *
+ * @throws RuntimeException if the specified [size] is negative.
+ */
+@ExperimentalStdlibApi
+@Suppress("UNCHECKED_CAST")
+public inline fun <reified T> AtomicArray(size: Int, init: (Int) -> T): AtomicArray<T> {
+ val inner = arrayOfNulls<T>(size)
+ for (index in 0 until size) {
+ inner[index] = init(index)
+ }
+ return AtomicArray(inner as Array<T>)
+}
\ No newline at end of file
diff --git a/libraries/stdlib/src/kotlin/concurrent/Atomics.common.kt b/libraries/stdlib/src/kotlin/concurrent/Atomics.common.kt
new file mode 100644
index 0000000..3db7a6c
--- /dev/null
+++ b/libraries/stdlib/src/kotlin/concurrent/Atomics.common.kt
@@ -0,0 +1,342 @@
+/*
+ * 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.
+ */
+
+package kotlin.concurrent
+
+import kotlin.internal.ActualizeByJvmBuiltinProvider
+
+/**
+ * An [Int] value that may be updated atomically with guaranteed sequential consistent ordering.
+ *
+ * Platform-specific implementation details:
+ *
+ * When targeting the Native backend, [AtomicInt] stores a volatile [Int] variable and atomically updates it.
+ * For additional details about atomicity guarantees for reads and writes see [kotlin.concurrent.Volatile].
+ *
+ * When targeting the JVM, instances of [AtomicInt] are represented by [java.util.concurrent.atomic.AtomicInteger].
+ * For details about guarantees of volatile accesses and updates of atomics refer to The Java Language Specification (17.4 Memory Model).
+ *
+ * For JS and Wasm [AtomicInt] is implemented trivially and is not thread-safe since these platforms do not support multi-threading.
+ */
+@ActualizeByJvmBuiltinProvider
+@ExperimentalStdlibApi
+public expect class AtomicInt public constructor(value: Int) {
+ /**
+ * Atomically gets the value of the atomic.
+ *
+ * Provides sequential consistent ordering guarantees.
+ */
+ public fun load(): Int
+
+ /**
+ * Atomically sets the value of the atomic to the [new value][newValue].
+ *
+ * Provides sequential consistent ordering guarantees.
+ */
+ public fun store(newValue: Int)
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] and returns the old value.
+ */
+ public fun exchange(newValue: Int): Int
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] if the current value equals the [expected value][expectedValue],
+ * returns true if the operation was successful and false only if the current value was not equal to the expected value.
+ *
+ * Provides sequential consistent ordering guarantees and cannot fail spuriously.
+ *
+ * Comparison of values is done by value.
+ */
+ public fun compareAndSet(expectedValue: Int, newValue: Int): Boolean
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] if the current value equals the [expected value][expected]
+ * and returns the old value in any case.
+ *
+ * Provides sequential consistent ordering guarantees and cannot fail spuriously.
+ *
+ * Comparison of values is done by value.
+ */
+ public fun compareAndExchange(expected: Int, newValue: Int): Int
+
+ /**
+ * Atomically adds the [given value][delta] to the current value and returns the old value.
+ */
+ public fun fetchAndAdd(delta: Int): Int
+
+ /**
+ * Atomically adds the [given value][delta] to the current value and returns the new value.
+ */
+ public fun addAndFetch(delta: Int): Int
+
+ /**
+ * Atomically increments the current value by one and returns the old value.
+ */
+ public fun fetchAndIncrement(): Int
+
+ /**
+ * Atomically increments the current value by one and returns the new value.
+ */
+ public fun incrementAndFetch(): Int
+
+ /**
+ * Atomically decrements the current value by one and returns the new value.
+ */
+ public fun decrementAndFetch(): Int
+
+ /**
+ * Atomically decrements the current value by one and returns the old value.
+ */
+ public fun fetchAndDecrement(): Int
+
+ /**
+ * Returns the string representation of the underlying [Int] value.
+ *
+ * This operation does not provide any atomicity guarantees.
+ */
+ public override fun toString(): String
+}
+
+/**
+ * Atomically adds the [given value][delta] to the current value.
+ */
+@ExperimentalStdlibApi
+public operator fun AtomicInt.plusAssign(delta: Int): Unit { this.addAndFetch(delta) }
+
+/**
+ * Atomically subtracts the [given value][delta] from the current value.
+ */
+@ExperimentalStdlibApi
+public operator fun AtomicInt.minusAssign(delta: Int): Unit { this.addAndFetch(-delta) }
+
+/**
+ * A [Long] value that may be updated atomically with guaranteed sequential consistent ordering.
+ *
+ * Platform-specific implementation details:
+ *
+ * When targeting the Native backend, [AtomicLong] stores a volatile [Long] variable and atomically updates it.
+ * For additional details about atomicity guarantees for reads and writes see [kotlin.concurrent.Volatile].
+ *
+ * When targeting the JVM, instances of [AtomicLong] are represented by [java.util.concurrent.atomic.AtomicLong].
+ * For details about guarantees of volatile accesses and updates of atomics refer to The Java Language Specification (17.4 Memory Model).
+ *
+ * For JS and Wasm [AtomicLong] is implemented trivially and is not thread-safe since these platforms do not support multi-threading.
+ */
+@ActualizeByJvmBuiltinProvider
+@ExperimentalStdlibApi
+public expect class AtomicLong public constructor(value: Long) {
+ /**
+ * Atomically gets the value of the atomic.
+ *
+ * Provides sequential consistent ordering guarantees.
+ */
+ public fun load(): Long
+
+ /**
+ * Atomically sets the value of the atomic to the [new value][newValue].
+ *
+ * Provides sequential consistent ordering guarantees.
+ */
+ public fun store(newValue: Long)
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] and returns the old value.
+ */
+ public fun exchange(newValue: Long): Long
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] if the current value equals the [expected value][expected],
+ * returns true if the operation was successful and false only if the current value was not equal to the expected value.
+ *
+ * Provides sequential consistent ordering guarantees and cannot fail spuriously.
+ *
+ * Comparison of values is done by value.
+ */
+ public fun compareAndSet(expected: Long, newValue: Long): Boolean
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] if the current value equals the [expected value][expected]
+ * and returns the old value in any case.
+ *
+ * Provides sequential consistent ordering guarantees and cannot fail spuriously.
+ *
+ * Comparison of values is done by value.
+ */
+ public fun compareAndExchange(expected: Long, newValue: Long): Long
+
+ /**
+ * Atomically adds the [given value][delta] to the current value and returns the old value.
+ */
+ public fun fetchAndAdd(delta: Long): Long
+
+ /**
+ * Atomically adds the [given value][delta] to the current value and returns the new value.
+ */
+ public fun addAndFetch(delta: Long): Long
+
+ /**
+ * Atomically increments the current value by one and returns the old value.
+ */
+ public fun fetchAndIncrement(): Long
+
+ /**
+ * Atomically increments the current value by one and returns the new value.
+ */
+ public fun incrementAndFetch(): Long
+
+ /**
+ * Atomically decrements the current value by one and returns the new value.
+ */
+ public fun decrementAndFetch(): Long
+
+ /**
+ * Atomically decrements the current value by one and returns the old value.
+ */
+ public fun fetchAndDecrement(): Long
+
+ /**
+ * Returns the string representation of the underlying [Long] value.
+ *
+ * This operation does not provide any atomicity guarantees.
+ */
+ public override fun toString(): String
+}
+
+/**
+ * Atomically adds the [given value][delta] to the current value.
+ */
+@ExperimentalStdlibApi
+public operator fun AtomicLong.plusAssign(delta: Long): Unit { this.addAndFetch(delta) }
+
+/**
+ * Atomically subtracts the [given value][delta] from the current value.
+ */
+@ExperimentalStdlibApi
+public operator fun AtomicLong.minusAssign(delta: Long): Unit { this.addAndFetch(-delta) }
+
+/**
+ * A [Boolean] value that may be updated atomically with guaranteed sequential consistent ordering.
+ *
+ * Platform-specific implementation details:
+ *
+ * When targeting the Native backend, [AtomicBoolean] stores a volatile [Boolean] variable and atomically updates it.
+ * For additional details about atomicity guarantees for reads and writes see [kotlin.concurrent.Volatile].
+ *
+ * When targeting the JVM, instances of [AtomicBoolean] are represented by [java.util.concurrent.atomic.AtomicInteger].
+ * For details about guarantees of volatile accesses and updates of atomics refer to The Java Language Specification (17.4 Memory Model).
+ *
+ * For JS and Wasm [AtomicBoolean] is implemented trivially and is not thread-safe since these platforms do not support multi-threading.
+ */
+@ActualizeByJvmBuiltinProvider
+@ExperimentalStdlibApi
+public expect class AtomicBoolean public constructor(value: Boolean) {
+ /**
+ * Atomically gets the value of the atomic.
+ *
+ * Provides sequential consistent ordering guarantees.
+ */
+ public fun load(): Boolean
+
+ /**
+ * Atomically sets the value of the atomic to the [new value][newValue].
+ *
+ * Provides sequential consistent ordering guarantees.
+ */
+ public fun store(newValue: Boolean)
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] and returns the old value.
+ */
+ public fun exchange(newValue: Boolean): Boolean
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] if the current value equals the [expected value][expected],
+ * returns true if the operation was successful and false only if the current value was not equal to the expected value.
+ *
+ * Provides sequential consistent ordering guarantees and cannot fail spuriously.
+ *
+ * Comparison of values is done by value.
+ */
+ public fun compareAndSet(expected: Boolean, newValue: Boolean): Boolean
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] if the current value equals the [expected value][expected]
+ * and returns the old value in any case.
+ *
+ * Provides sequential consistent ordering guarantees and cannot fail spuriously.
+ *
+ * Comparison of values is done by value.
+ */
+ public fun compareAndExchange(expected: Boolean, newValue: Boolean): Boolean
+
+ /**
+ * Returns the string representation of the current [Boolean] value.
+ */
+ public override fun toString(): String
+}
+
+/**
+ * An object reference that may be updated atomically with guaranteed sequential consistent ordering.
+ *
+ * Platform-specific implementation details:
+ *
+ * When targeting the Native backend, [AtomicReference] stores a volatile variable of type [T] and atomically updates it.
+ * For additional details about atomicity guarantees for reads and writes see [kotlin.concurrent.Volatile].
+ *
+ * When targeting the JVM, instances of [AtomicReference] are represented by [java.util.concurrent.atomic.AtomicReference].
+ * For details about guarantees of volatile accesses and updates of atomics refer to The Java Language Specification (17.4 Memory Model).
+ *
+ * For JS and Wasm [AtomicReference] is implemented trivially and is not thread-safe since these platforms do not support multi-threading.
+ */
+@ActualizeByJvmBuiltinProvider
+@ExperimentalStdlibApi
+public expect class AtomicReference<T> public constructor(value: T) {
+ /**
+ * Atomically gets the value of the atomic.
+ *
+ * Provides sequential consistent ordering guarantees.
+ */
+ public fun load(): T
+
+ /**
+ * Atomically sets the value of the atomic to the [new value][newValue].
+ *
+ * Provides sequential consistent ordering guarantees.
+ */
+ public fun store(newValue: T)
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] and returns the old value.
+ */
+ public fun exchange(newValue: T): T
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] if the current value equals the [expected value][expected],
+ * returns true if the operation was successful and false only if the current value was not equal to the expected value.
+ *
+ * Provides sequential consistent ordering guarantees and cannot fail spuriously.
+ *
+ * Comparison of values is done by reference.
+ */
+ public fun compareAndSet(expected: T, newValue: T): Boolean
+
+ /**
+ * Atomically sets the value to the given [new value][newValue] if the current value equals the [expected value][expected]
+ * and returns the old value in any case.
+ *
+ * Provides sequential consistent ordering guarantees and cannot fail spuriously.
+ *
+ * Comparison of values is done by reference.
+ */
+ public fun compareAndExchange(expected: T, newValue: T): T
+
+ /**
+ * Returns the string representation of the underlying object.
+ *
+ * This operation does not provide any atomicity guarantees.
+ */
+ public override fun toString(): String
+}
diff --git a/libraries/stdlib/test/concurrent/AtomicArrayCommonTest.kt b/libraries/stdlib/test/concurrent/AtomicArrayCommonTest.kt
new file mode 100644
index 0000000..31cb1e6
--- /dev/null
+++ b/libraries/stdlib/test/concurrent/AtomicArrayCommonTest.kt
@@ -0,0 +1,572 @@
+/*
+ * 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.
+ */
+
+package test.concurrent
+
+import kotlin.concurrent.*
+import kotlin.test.*
+
+class AtomicIntArrayTest {
+ @Test fun ctor() {
+ val arr1 = AtomicIntArray(6)
+ assertEquals(0, arr1.loadAt(4))
+ assertEquals(6, arr1.size)
+
+ val arr2 = AtomicIntArray(10) { i: Int -> i * 10 }
+ assertEquals(40, arr2.loadAt(4))
+ assertEquals(10, arr2.size)
+
+ val emptyArr = AtomicIntArray(0)
+ assertEquals(0, emptyArr.size)
+
+ assertFails {
+ val arrNegativeSize = AtomicIntArray(-5)
+ }
+ }
+
+ @Test fun getter() {
+ val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
+ for (i in 0 until atomicIntArr.size) {
+ assertEquals(i * 10, atomicIntArr.loadAt(i), "getter: FAIL $i")
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicIntArr.loadAt(22)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(22), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicIntArr.loadAt(-1)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+
+ @Test fun setter() {
+ val atomicIntArr = AtomicIntArray(10)
+ for (i in 0 until atomicIntArr.size) {
+ atomicIntArr.storeAt(i, i * 10)
+ }
+ for (i in 0 until atomicIntArr.size) {
+ assertEquals(i * 10, atomicIntArr.loadAt(i), "setter: FAIL $i")
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ atomicIntArr.storeAt(22, 100)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(22), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ atomicIntArr.storeAt(-1, 100)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+
+ @Test fun addAndFetchAt() {
+ val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
+ assertEquals(110, atomicIntArr.addAndFetchAt(1, 100), "addAndFetchAt: FAIL 1")
+ assertEquals(110, atomicIntArr.loadAt(1), "addAndFetchAt: FAIL 2")
+ assertEquals(10, atomicIntArr.addAndFetchAt(1, -100), "addAndFetchAt: FAIL 3")
+ assertEquals(10, atomicIntArr.loadAt(1), "addAndFetchAt: FAIL 4")
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicIntArr.addAndFetchAt(22, 33535)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(22), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicIntArr.addAndFetchAt(-1, 33535)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+
+ @Test fun compareAndExchange() {
+ val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
+ val res1 = atomicIntArr.compareAndExchangeAt(2, 20, 222) // success
+ assertTrue(res1 == 20 && atomicIntArr.loadAt(2) == 222, "compareAndExchange: FAIL 1")
+ val res2 = atomicIntArr.compareAndExchangeAt(2, 222, 2222) // success
+ assertTrue(res2 == 222 && atomicIntArr.loadAt(2) == 2222, "compareAndExchangeAt: FAIL 2")
+ val res3 = atomicIntArr.compareAndExchangeAt(2, 223, 22222) // should fail
+ assertTrue(res3 == 2222 && atomicIntArr.loadAt(2) == 2222, "compareAndExchangeAt: FAIL 3")
+ val res4 = atomicIntArr.compareAndExchangeAt(9, 10, 999) // should fail
+ assertTrue(res4 == 90 && atomicIntArr.loadAt(9) == 90, "compareAndExchangeAt: FAIL 4")
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicIntArr.compareAndExchangeAt(10, 33535, 39530)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(10), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicIntArr.compareAndExchangeAt(-1, 33535, 39530)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+
+ @Test fun compareAndSetAt() {
+ val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
+ val res1 = atomicIntArr.compareAndSetAt(2, 20, 222) // success
+ assertTrue(res1 && atomicIntArr.loadAt(2) == 222, "compareAndSetAt: FAIL 1")
+ val res2 = atomicIntArr.compareAndSetAt(2, 222, 2222) // success
+ assertTrue(res2 && atomicIntArr.loadAt(2) == 2222, "compareAndSetAt: FAIL 2")
+ val res3 = atomicIntArr.compareAndSetAt(2, 223, 22222) // should fail
+ assertTrue(!res3 && atomicIntArr.loadAt(2) == 2222, "compareAndSetAt: FAIL 3")
+ val res4 = atomicIntArr.compareAndSetAt(9, 10, 999) // should fail
+ assertTrue(!res4 && atomicIntArr.loadAt(9) == 90, "compareAndSetAt: FAIL 4")
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicIntArr.compareAndSetAt(10, 33535, 39530)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(10), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicIntArr.compareAndSetAt(-1, 33535, 39530)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+
+ @Test fun exchangeAt() {
+ val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
+ assertEquals(20, atomicIntArr.exchangeAt(2, 200), "exchangeAt: FAIL 1")
+ assertEquals(200, atomicIntArr.exchangeAt(2, 2000), "exchangeAt: FAIL 2")
+ assertEquals(2000, atomicIntArr.loadAt(2), "exchangeAt: FAIL 3")
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicIntArr.exchangeAt(22, 33535)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(22), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicIntArr.exchangeAt(-1, 33535)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+
+ @Test fun fetchAndAddAt() {
+ val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
+ assertEquals(10, atomicIntArr.fetchAndAddAt(1, 100), "fetchAndAddAt: FAIL 1")
+ assertEquals(110, atomicIntArr.loadAt(1), "fetchAndAddAt: FAIL 2")
+ assertEquals(110, atomicIntArr.fetchAndAddAt(1, -100), "fetchAndAddAt: FAIL 3")
+ assertEquals(10, atomicIntArr.loadAt(1), "fetchAndAddAt: FAIL 4")
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicIntArr.fetchAndAddAt(22, 33535)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(22), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicIntArr.fetchAndAddAt(-1, 33535)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+
+ @Test fun fetchAndIncrementAt() {
+ val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
+ assertEquals(10, atomicIntArr.fetchAndIncrementAt(1), "fetchAndIncrementAt: FAIL 1")
+ assertEquals(11, atomicIntArr.loadAt(1), "fetchAndIncrementAt: FAIL 2")
+ assertEquals(11, atomicIntArr.fetchAndIncrementAt(1), "fetchAndIncrementAt: FAIL 3")
+ assertEquals(12, atomicIntArr.loadAt(1), "fetchAndIncrementAt: FAIL 4")
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicIntArr.fetchAndIncrementAt(22)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(22), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicIntArr.fetchAndIncrementAt(-1)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+
+ @Test fun incrementAndFetchAt() {
+ val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
+ assertEquals(11, atomicIntArr.incrementAndFetchAt(1), "incrementAndFetchAt: FAIL 1")
+ assertEquals(11, atomicIntArr.loadAt(1), "incrementAndFetchAt: FAIL 2")
+ assertEquals(12, atomicIntArr.incrementAndFetchAt(1), "incrementAndFetchAt: FAIL 3")
+ assertEquals(12, atomicIntArr.loadAt(1), "incrementAndFetchAt: FAIL 4")
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicIntArr.incrementAndFetchAt(22)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(22), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicIntArr.incrementAndFetchAt(-1)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+
+ @Test fun fetchAndDecrementAt() {
+ val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
+ assertEquals(10, atomicIntArr.fetchAndDecrementAt(1), "fetchAndDecrementAt: FAIL 1")
+ assertEquals(9, atomicIntArr.loadAt(1), "fetchAndDecrementAt: FAIL 2")
+ assertEquals(9, atomicIntArr.fetchAndDecrementAt(1), "fetchAndDecrementAt: FAIL 3")
+ assertEquals(8, atomicIntArr.loadAt(1), "fetchAndDecrementAt: FAIL 4")
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicIntArr.fetchAndDecrementAt(22)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(22), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicIntArr.fetchAndDecrementAt(-1)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+
+ @Test fun decrementAndFetchAt() {
+ val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
+ assertEquals(9, atomicIntArr.decrementAndFetchAt(1), "decrementAndFetchAt: FAIL 1")
+ assertEquals(9, atomicIntArr.loadAt(1), "decrementAndFetchAt: FAIL 2")
+ assertEquals(8, atomicIntArr.decrementAndFetchAt(1), "decrementAndFetchAt: FAIL 3")
+ assertEquals(8, atomicIntArr.loadAt(1), "decrementAndFetchAt: FAIL 4")
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicIntArr.decrementAndFetchAt(22)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(22), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicIntArr.decrementAndFetchAt(-1)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+}
+
+class AtomicLongArrayTest {
+ @Test fun ctor() {
+ val arr1 = AtomicLongArray(6)
+ assertEquals(arr1.loadAt(4), 0L)
+ assertEquals(arr1.size, 6)
+ val arr2 = AtomicLongArray(10) { i: Int -> i * 10L }
+ assertEquals(arr2.loadAt(4), 40L)
+ assertEquals(arr2.size, 10)
+
+ val emptyArr = AtomicLongArray(0)
+ assertEquals(emptyArr.size, 0)
+
+ assertFails {
+ val arrNegativeSize = AtomicLongArray(-5)
+ }
+ }
+
+ @Test fun getter() {
+ val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
+ for (i in 0 until atomicLongArr.size) {
+ assertEquals(i * 10L, atomicLongArr.loadAt(i), "getter: FAIL $i")
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicLongArr.loadAt(22)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(22), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicLongArr.loadAt(-1)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+
+ @Test fun setter() {
+ val atomicLongArr = AtomicLongArray(10)
+ for (i in 0 until atomicLongArr.size) {
+ atomicLongArr.storeAt(i, i * 10L)
+ }
+ for (i in 0 until atomicLongArr.size) {
+ assertEquals(i * 10L, atomicLongArr.loadAt(i), "setter: FAIL $i")
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ atomicLongArr.storeAt(10, 3998009)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(10), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ atomicLongArr.storeAt(-1, 3998009)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+
+ @Test fun addAndFetchAt() {
+ val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
+ assertEquals(110L, atomicLongArr.addAndFetchAt(1, 100L), "addAndFetchAt: FAIL 1")
+ assertEquals(110L, atomicLongArr.loadAt(1), "addAndFetchAt: FAIL 2")
+ assertEquals(10L, atomicLongArr.addAndFetchAt(1, -100L), "addAndFetchAt: FAIL 3")
+ assertEquals(10L, atomicLongArr.loadAt(1), "addAndFetchAt: FAIL 4")
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicLongArr.addAndFetchAt(22, 33535)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(22), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicLongArr.addAndFetchAt(-1, 33535)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+
+ @Test fun compareAndExchangeAt() {
+ val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
+ val res1 = atomicLongArr.compareAndExchangeAt(2, 20L, 222L) // success
+ assertTrue(res1 == 20L && atomicLongArr.loadAt(2) == 222L, "compareAndExchangeAt: FAIL 1")
+ val res2 = atomicLongArr.compareAndExchangeAt(2, 222L, 2222L) // success
+ assertTrue(res2 == 222L && atomicLongArr.loadAt(2) == 2222L, "compareAndExchangeAt: FAIL 2")
+ val res3 = atomicLongArr.compareAndExchangeAt(2, 223L, 22222L) // should fail
+ assertTrue(res3 == 2222L && atomicLongArr.loadAt(2) == 2222L, "compareAndExchangeAt: FAIL 3")
+ val res4 = atomicLongArr.compareAndExchangeAt(9, 10L, 999L) // should fail
+ assertTrue(res4 == 90L && atomicLongArr.loadAt(9) == 90L, "compareAndExchangeAt: FAIL 4")
+ assertFailsWith<IndexOutOfBoundsException> {
+ atomicLongArr.compareAndExchangeAt(10, 9353, 39058308)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(10), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ atomicLongArr.compareAndExchangeAt(-1, 9353, 39058308)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+
+ @Test fun compareAndSetAt() {
+ val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
+ val res1 = atomicLongArr.compareAndSetAt(2, 20L, 222L) // success
+ assertTrue(res1 && atomicLongArr.loadAt(2) == 222L, "compareAndSetAt: FAIL 1")
+ val res2 = atomicLongArr.compareAndSetAt(2, 222L, 2222L) // success
+ assertTrue(res2 && atomicLongArr.loadAt(2) == 2222L, "compareAndSetAt: FAIL 2")
+ val res3 = atomicLongArr.compareAndSetAt(2, 223L, 22222L) // should fail
+ assertTrue(!res3 && atomicLongArr.loadAt(2) == 2222L, "compareAndSetAt: FAIL 3")
+ val res4 = atomicLongArr.compareAndSetAt(9, 10L, 999L) // should fail
+ assertTrue(!res4 && atomicLongArr.loadAt(9) == 90L, "compareAndSetAt: FAIL 4")
+ assertFailsWith<IndexOutOfBoundsException> {
+ atomicLongArr.compareAndSetAt(10, 9353, 39058308)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(10), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ atomicLongArr.compareAndSetAt(-1, 9353, 39058308)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+
+ @Test fun exchangeAt() {
+ val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
+ assertEquals(20L, atomicLongArr.exchangeAt(2, 200L), "exchangeAt: FAIL 1")
+ assertEquals(200L, atomicLongArr.exchangeAt(2, 2000L), "exchangeAt: FAIL 2")
+ assertEquals(2000L, atomicLongArr.loadAt(2), "exchangeAt: FAIL 3")
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicLongArr.exchangeAt(22, 9353)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(22), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicLongArr.exchangeAt(-1, 9353)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+
+ @Test fun fetchAndAddAt() {
+ val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
+ assertEquals(10L, atomicLongArr.fetchAndAddAt(1, 100L), "fetchAndAddAt: FAIL 1")
+ assertEquals(110L, atomicLongArr.loadAt(1), "fetchAndAddAt: FAIL 2")
+ assertEquals(110L, atomicLongArr.fetchAndAddAt(1, -100L), "fetchAndAddAt: FAIL 3")
+ assertEquals(10L, atomicLongArr.loadAt(1), "fetchAndAddAt: FAIL 4")
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicLongArr.fetchAndAddAt(100, 9353)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(100), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicLongArr.fetchAndAddAt(-1, 9353)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+
+ @Test fun fetchAndIncrementAt() {
+ val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
+ assertEquals(10L, atomicLongArr.fetchAndIncrementAt(1), "fetchAndIncrementAt: FAIL 1")
+ assertEquals(11L, atomicLongArr.loadAt(1), "fetchAndIncrementAt: FAIL 2")
+ assertEquals(11L, atomicLongArr.fetchAndIncrementAt(1), "fetchAndIncrementAt: FAIL 3")
+ assertEquals(12L, atomicLongArr.loadAt(1), "fetchAndIncrementAt: FAIL 4")
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicLongArr.fetchAndIncrementAt(22)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(22), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicLongArr.addAndFetchAt(-1, 33535)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+
+ @Test fun incrementAndFetchAt() {
+ val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
+ assertEquals(11L, atomicLongArr.incrementAndFetchAt(1), "incrementAndFetchAt: FAIL 1")
+ assertEquals(11L, atomicLongArr.loadAt(1), "incrementAndFetchAt: FAIL 2")
+ assertEquals(12L, atomicLongArr.incrementAndFetchAt(1), "incrementAndFetchAt: FAIL 3")
+ assertEquals(12L, atomicLongArr.loadAt(1), "incrementAndFetchAt: FAIL 4")
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicLongArr.incrementAndFetchAt(22)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(22), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicLongArr.incrementAndFetchAt(-1)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+
+ @Test fun fetchAndDecrementAt() {
+ val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
+ assertEquals(10L, atomicLongArr.fetchAndDecrementAt(1), "fetchAndDecrementAt: FAIL 1")
+ assertEquals(9L, atomicLongArr.loadAt(1), "fetchAndDecrementAt: FAIL 2")
+ assertEquals(9L, atomicLongArr.fetchAndDecrementAt(1), "fetchAndDecrementAt: FAIL 3")
+ assertEquals(8L, atomicLongArr.loadAt(1), "fetchAndDecrementAt: FAIL 4")
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicLongArr.fetchAndDecrementAt(22)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(22), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicLongArr.fetchAndDecrementAt(-1)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+
+ @Test fun decrementAndFetchAt() {
+ val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
+ assertEquals(9L, atomicLongArr.decrementAndFetchAt(1), "decrementAndFetchAt: FAIL 1")
+ assertEquals(9L, atomicLongArr.loadAt(1), "decrementAndFetchAt: FAIL 2")
+ assertEquals(8L, atomicLongArr.decrementAndFetchAt(1), "decrementAndFetchAt: FAIL 3")
+ assertEquals(8L, atomicLongArr.loadAt(1), "decrementAndFetchAt: FAIL 4")
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicLongArr.decrementAndFetchAt(22)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(22), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = atomicLongArr.decrementAndFetchAt(-1)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+}
+
+class AtomicArrayTest {
+ @Test fun ctor() {
+ val arr2 = AtomicArray<Data?>(10) { null }
+ assertEquals(arr2.loadAt(4), null)
+ assertEquals(arr2.size, 10)
+
+ val emptyArr = AtomicArray<Data?>(0) { Data(1) }
+ assertEquals(emptyArr.size, 0)
+
+ assertFails {
+ val arrNegativeSize = AtomicArray<Data?>(-5) { Data(1) }
+ }
+ }
+
+ @Test fun getter() {
+ val refArr = AtomicArray<Data?>(10) { i -> Data(i) }
+ for (i in 0 until refArr.size) {
+ assertEquals(Data(i), refArr.loadAt(i), "getter: FAIL $i")
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = refArr.loadAt(100)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(100), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ val res = refArr.loadAt(-1)
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+
+ @Test fun setter() {
+ val refArr = AtomicArray<Data?>(10) { null }
+ for (i in 0 until refArr.size) {
+ refArr.storeAt(i, Data(i))
+ }
+ for (i in 0 until refArr.size) {
+ assertEquals(Data(i), refArr.loadAt(i), "setter: FAIL $i")
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ refArr.storeAt(100, Data(100))
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(100), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ refArr.storeAt(-1, Data(-1))
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+
+ @Test fun compareAndExchangeAt() {
+ val refArr = AtomicArray<Data?>(10) { null }
+ val newValue = Data(1)
+ val res1 = refArr.compareAndExchangeAt(3, null, newValue)
+ assertTrue(res1 == null && refArr.loadAt(3) == newValue, "compareAndExchangeAt: FAIL 1")
+ val res2 = refArr.compareAndExchangeAt(3, newValue, Data(2))
+ assertTrue(res2 == newValue && refArr.loadAt(3) == Data(2), "compareAndExchangeAt: FAIL 2")
+ val res3 = refArr.compareAndExchangeAt(3, newValue, Data(3))
+ assertTrue(res3 == Data(2) && refArr.loadAt(3) == Data(2), "compareAndExchangeAt: FAIL 3")
+ assertFailsWith<IndexOutOfBoundsException> {
+ refArr.compareAndExchangeAt(10, newValue, Data(4))
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(10), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ refArr.compareAndExchangeAt(-1, newValue, Data(4))
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+
+ @Test fun compareAndSetAt() {
+ val refArr = AtomicArray<Data?>(10) { null }
+ val newValue = Data(1)
+ val res1 = refArr.compareAndSetAt(3, null, newValue)
+ assertTrue(res1 && refArr.loadAt(3) == newValue, "testAtomicArraycompareAndSetAt: FAIL 1")
+ val res2 = refArr.compareAndSetAt(3, newValue, Data(2))
+ assertTrue(res2 && refArr.loadAt(3) == Data(2), "testAtomicArraycompareAndSetAt: FAIL 2")
+ val res3 = refArr.compareAndSetAt(3, newValue, Data(3))
+ assertTrue(!res3 && refArr.loadAt(3) == Data(2), "testAtomicArraycompareAndSetAt: FAIL 3")
+ assertFailsWith<IndexOutOfBoundsException> {
+ refArr.compareAndSetAt(10, newValue, Data(4))
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(10), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ refArr.compareAndSetAt(-1, newValue, Data(4))
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+
+ @Test fun exchangeAt() {
+ val refArr = AtomicArray<Data?>(10) { null }
+ val res4 = refArr.exchangeAt(4, Data(1))
+ assertEquals(null, res4, "exchangeAt: FAIL 1")
+ val res5 = refArr.exchangeAt(4, Data(2))
+ assertEquals(Data(1), res5, "exchangeAt: FAIL 2")
+ assertFailsWith<IndexOutOfBoundsException> {
+ refArr.exchangeAt(10, Data(1))
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(10), ex.message)
+ }
+ assertFailsWith<IndexOutOfBoundsException> {
+ refArr.exchangeAt(-1, Data(1))
+ }.let { ex ->
+ assertEquals(indexOutBoundsError(-1), ex.message)
+ }
+ }
+}
+
+private fun indexOutBoundsError(index: Int) = "index $index"
\ No newline at end of file
diff --git a/libraries/stdlib/test/concurrent/AtomicCommonTest.kt b/libraries/stdlib/test/concurrent/AtomicCommonTest.kt
new file mode 100644
index 0000000..8e6760b
--- /dev/null
+++ b/libraries/stdlib/test/concurrent/AtomicCommonTest.kt
@@ -0,0 +1,241 @@
+/*
+ * 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.
+ */
+
+package test.concurrent
+
+import kotlin.concurrent.*
+import kotlin.test.*
+
+data class Data(val value: Int)
+
+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))
+ }
+}
+
+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))
+ }
+}
+
+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())
+ }
+}
+
+class AtomicReferenceTest {
+ @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))))
+ }
+}
\ No newline at end of file
diff --git a/libraries/stdlib/wasm/src/kotlin/concurrent/AtomicArrays.wasm.kt b/libraries/stdlib/wasm/src/kotlin/concurrent/AtomicArrays.wasm.kt
new file mode 100644
index 0000000..b9ffa98
--- /dev/null
+++ b/libraries/stdlib/wasm/src/kotlin/concurrent/AtomicArrays.wasm.kt
@@ -0,0 +1,438 @@
+/*
+ * 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.
+ */
+
+package kotlin.concurrent
+
+/**
+ * An array of ints which provides API of the common [AtomicIntArray].
+ *
+ * Does not provide any atomicity guarantees since the WASM platform does not support multi-threading.
+ */
+public actual class AtomicIntArray {
+ private val array: IntArray
+
+ /**
+ * Creates a new [AtomicIntArray] of the given [size], with all elements initialized to zero.
+ *
+ * @throws RuntimeException if the specified [size] is negative.
+ */
+ public actual constructor(size: Int) {
+ array = IntArray(size)
+ }
+
+ /**
+ * Creates a new [AtomicIntArray] filled with elements of the given [array].
+ */
+ public actual constructor(array: IntArray) {
+ this.array = array.copyOf()
+ }
+
+ /**
+ * Returns the number of elements in the array.
+ */
+ public actual val size: Int get() = array.size
+
+ /**
+ * Gets the value of the element at the given [index].
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun loadAt(index: Int): Int {
+ checkBounds(index)
+ return array[index]
+ }
+
+ /**
+ * Sets the value of the element at the given [index] to the [new value][newValue].
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun storeAt(index: Int, newValue: Int) {
+ checkBounds(index)
+ array[index] = newValue
+ }
+
+ /**
+ * Sets the value of the element at the given [index] to the [new value][newValue]
+ * and returns the old value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun exchangeAt(index: Int, newValue: Int): Int {
+ checkBounds(index)
+ val oldValue = array[index]
+ array[index] = newValue
+ return oldValue
+ }
+
+ /**
+ * Sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue].
+ * Returns true if the operation was successful and false only if the current value of the element was not equal to the expected value.
+ *
+ * Comparison of values is done by value.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun compareAndSetAt(index: Int, expectedValue: Int, newValue: Int): Boolean {
+ checkBounds(index)
+ if (array[index] != expectedValue) return false
+ array[index] = newValue
+ return true
+ }
+
+ /**
+ * Sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue] and returns the old value of the element in any case.
+ *
+ * Comparison of values is done by value.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun compareAndExchangeAt(index: Int, expectedValue: Int, newValue: Int): Int {
+ checkBounds(index)
+ val oldValue = array[index]
+ if (oldValue == expectedValue) {
+ array[index] = newValue
+ }
+ return oldValue
+ }
+
+ /**
+ * Adds the given [delta] to the element at the given [index] and returns the old value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun fetchAndAddAt(index: Int, delta: Int): Int {
+ checkBounds(index)
+ val oldValue = array[index]
+ array[index] += delta
+ return oldValue
+ }
+
+ /**
+ * Adds the given [delta] to the element at the given [index] and returns the new value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun addAndFetchAt(index: Int, delta: Int): Int {
+ checkBounds(index)
+ array[index] += delta
+ return array[index]
+ }
+
+ /**
+ * Increments the element at the given [index] by one and returns the old value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun fetchAndIncrementAt(index: Int): Int {
+ checkBounds(index)
+ return array[index]++
+ }
+
+ /**
+ * Increments the element at the given [index] by one and returns the new value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun incrementAndFetchAt(index: Int): Int {
+ checkBounds(index)
+ return ++array[index]
+ }
+
+ /**
+ * Decrements the element at the given [index] by one and returns the old value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun fetchAndDecrementAt(index: Int): Int {
+ checkBounds(index)
+ return array[index]--
+ }
+
+ /**
+ * Decrements the element at the given [index] by one and returns the new value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun decrementAndFetchAt(index: Int): Int {
+ checkBounds(index)
+ return --array[index]
+ }
+
+ /**
+ * Returns the string representation of the underlying array of ints.
+ */
+ public actual override fun toString(): String = array.toString()
+
+ private fun checkBounds(index: Int) {
+ if (index < 0 || index >= array.size) throw IndexOutOfBoundsException("index $index")
+ }
+}
+
+/**
+ * An array of longs which provides API of the common [AtomicLongArray].
+ *
+ * Does not provide any atomicity guarantees since the JS platform does not support multi-threading.
+ */
+public actual class AtomicLongArray {
+ private val array: LongArray
+
+ /**
+ * Creates a new [AtomicLongArray] of the given [size], with all elements initialized to zero.
+ *
+ * @throws RuntimeException if the specified [size] is negative.
+ */
+ public actual constructor(size: Int) {
+ array = LongArray(size)
+ }
+
+ /**
+ * Creates a new [AtomicIntArray] filled with elements of the given [array].
+ */
+ public actual constructor(array: LongArray) {
+ this.array = array.copyOf()
+ }
+
+ /**
+ * Returns the number of elements in the array.
+ */
+ public actual val size: Int get() = array.size
+
+ /**
+ * Gets the value of the element at the given [index].
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun loadAt(index: Int): Long {
+ checkBounds(index)
+ return array[index]
+ }
+
+ /**
+ * Sets the value of the element at the given [index] to the [new value][newValue].
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun storeAt(index: Int, newValue: Long) {
+ checkBounds(index)
+ array[index] = newValue
+ }
+
+ /**
+ * Sets the value of the element at the given [index] to the [new value][newValue]
+ * and returns the old value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun exchangeAt(index: Int, newValue: Long): Long {
+ checkBounds(index)
+ val oldValue = array[index]
+ array[index] = newValue
+ return oldValue
+ }
+
+ /**
+ * Sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue].
+ * Returns true if the operation was successful and false only if the current value of the element was not equal to the expected value.
+ *
+ * Comparison of values is done by value.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun compareAndSetAt(index: Int, expectedValue: Long, newValue: Long): Boolean {
+ checkBounds(index)
+ if (array[index] != expectedValue) return false
+ array[index] = newValue
+ return true
+ }
+
+ /**
+ * Sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue] and returns the old value of the element in any case.
+ *
+ * Comparison of values is done by value.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun compareAndExchangeAt(index: Int, expectedValue: Long, newValue: Long): Long {
+ checkBounds(index)
+ val oldValue = array[index]
+ if (oldValue == expectedValue) {
+ array[index] = newValue
+ }
+ return oldValue
+ }
+
+ /**
+ * Adds the given [delta] to the element at the given [index] and returns the old value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun fetchAndAddAt(index: Int, delta: Long): Long {
+ checkBounds(index)
+ val oldValue = array[index]
+ array[index] += delta
+ return oldValue
+ }
+
+ /**
+ * Adds the given [delta] to the element at the given [index] and returns the new value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun addAndFetchAt(index: Int, delta: Long): Long {
+ checkBounds(index)
+ array[index] += delta
+ return array[index]
+ }
+
+ /**
+ * Increments the element at the given [index] by one and returns the old value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun fetchAndIncrementAt(index: Int): Long {
+ checkBounds(index)
+ return array[index]++
+ }
+
+ /**
+ * Increments the element at the given [index] by one and returns the new value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun incrementAndFetchAt(index: Int): Long {
+ checkBounds(index)
+ return ++array[index]
+ }
+
+ /**
+ * Decrements the element at the given [index] by one and returns the old value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun fetchAndDecrementAt(index: Int): Long {
+ checkBounds(index)
+ return array[index]--
+ }
+
+ /**
+ * Decrements the element at the given [index] by one and returns the new value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun decrementAndFetchAt(index: Int): Long {
+ checkBounds(index)
+ return --array[index]
+ }
+
+ /**
+ * Returns the string representation of the underlying array of longs.
+ */
+ public actual override fun toString(): String = array.toString()
+
+ private fun checkBounds(index: Int) {
+ if (index < 0 || index >= array.size) throw IndexOutOfBoundsException("index $index")
+ }
+}
+
+/**
+ * An array of longs which provides API of the common [AtomicArray].
+ *
+ * Does not provide any atomicity guarantees since the JS platform does not support multi-threading.
+ */
+public actual class AtomicArray<T> {
+ private val array: Array<T>
+
+ /**
+ * Creates a new [AtomicArray] filled with elements of the given [array].
+ */
+ public actual constructor (array: Array<T>) {
+ this.array = array.copyOf()
+ }
+
+ /**
+ * Returns the number of elements in the array.
+ */
+ public actual val size: Int get() = array.size
+
+ /**
+ * Gets the value of the element at the given [index].
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun loadAt(index: Int): T {
+ checkBounds(index)
+ return array[index]
+ }
+
+ /**
+ * Sets the value of the element at the given [index] to the [new value][newValue].
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun storeAt(index: Int, newValue: T) {
+ checkBounds(index)
+ array[index] = newValue
+ }
+
+ /**
+ * Sets the value of the element at the given [index] to the [new value][newValue]
+ * and returns the old value of the element.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun exchangeAt(index: Int, newValue: T): T {
+ checkBounds(index)
+ val oldValue = array[index]
+ array[index] = newValue
+ return oldValue
+ }
+
+ /**
+ * Sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue].
+ * Returns true if the operation was successful and false only if the current value of the element was not equal to the expected value.
+ *
+ * Comparison of values is done by value.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun compareAndSetAt(index: Int, expectedValue: T, newValue: T): Boolean {
+ checkBounds(index)
+ if (array[index] != expectedValue) return false
+ array[index] = newValue
+ return true
+ }
+
+ /**
+ * Sets the value of the element at the given [index] to the [new value][newValue]
+ * if the current value equals the [expected value][expectedValue] and returns the old value of the element in any case.
+ *
+ * Comparison of values is done by value.
+ *
+ * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this array.
+ */
+ public actual fun compareAndExchangeAt(index: Int, expectedValue: T, newValue: T): T {
+ checkBounds(index)
+ val oldValue = array[index]
+ if (oldValue == expectedValue) {
+ array[index] = newValue
+ }
+ return oldValue
+ }
+
+ /**
+ * Returns the string representation of the underlying array of objects.
+ */
+ public actual override fun toString(): String = array.toString()
+
+ private fun checkBounds(index: Int) {
+ if (index < 0 || index >= array.size) throw IndexOutOfBoundsException("index $index")
+ }
+}
\ No newline at end of file
diff --git a/libraries/stdlib/wasm/src/kotlin/concurrent/Atomics.wasm.kt b/libraries/stdlib/wasm/src/kotlin/concurrent/Atomics.wasm.kt
new file mode 100644
index 0000000..8742829
--- /dev/null
+++ b/libraries/stdlib/wasm/src/kotlin/concurrent/Atomics.wasm.kt
@@ -0,0 +1,310 @@
+/*
+ * 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.
+ */
+
+package kotlin.concurrent
+
+/**
+ * An [Int] value which provides API of the common [AtomicInt].
+ *
+ * Does not provide any atomicity guarantees since the WASM platform does not support multi-threading.
+ */
+public actual class AtomicInt public actual constructor(private var value: Int) {
+
+ /**
+ * Gets the value of the atomic.
+ */
+ public actual fun load(): Int = value
+
+ /**
+ * Sets the value of the atomic to the [new value][newValue].
+ */
+ public actual fun store(newValue: Int) { value = newValue }
+
+ /**
+ * Sets the value to the given [new value][newValue] and returns the old value.
+ */
+ public actual fun exchange(newValue: Int): Int {
+ val oldValue = value
+ value = newValue
+ return oldValue
+ }
+
+ /**
+ * Sets the value to the given [new value][newValue] if the current value equals the [expected value][expectedValue],
+ * returns true if the operation was successful and false only if the current value was not equal to the expected value.
+ *
+ * Comparison of values is done by value.
+ */
+ public actual fun compareAndSet(expectedValue: Int, newValue: Int): Boolean {
+ if (value != expectedValue) return false
+ value = newValue
+ return true
+ }
+
+ /**
+ * Sets the value to the given [new value][newValue] if the current value equals the [expected value][expected]
+ * and returns the old value in any case.
+ *
+ * Comparison of values is done by value.
+ */
+ public actual fun compareAndExchange(expected: Int, newValue: Int): Int {
+ val oldValue = value
+ if (oldValue == expected) {
+ value = newValue
+ }
+ return oldValue
+ }
+
+ /**
+ * Adds the [given value][delta] to the current value and returns the old value.
+ */
+ public actual fun fetchAndAdd(delta: Int): Int {
+ val oldValue = value
+ value += delta
+ return oldValue
+ }
+
+ /**
+ * Adds the [given value][delta] to the current value and returns the new value.
+ */
+ public actual fun addAndFetch(delta: Int): Int {
+ value += delta
+ return value
+ }
+
+ /**
+ * Increments the current value by one and returns the old value.
+ */
+ public actual fun fetchAndIncrement(): Int = value++
+
+ /**
+ * Increments the current value by one and returns the new value.
+ */
+ public actual fun incrementAndFetch(): Int = ++value
+
+ /**
+ * Decrements the current value by one and returns the new value.
+ */
+ public actual fun fetchAndDecrement(): Int = value--
+
+ /**
+ * Decrements the current value by one and returns the old value.
+ */
+ public actual fun decrementAndFetch(): Int = --value
+
+ /**
+ * Returns the string representation of the underlying [Int] value.
+ */
+ public actual override fun toString(): String = value.toString()
+}
+
+/**
+ * An [Long] value which provides API of the common [AtomicLong].
+ *
+ * Does not provide any atomicity guarantees since the WASM platform does not support multi-threading.
+ */
+public actual class AtomicLong public actual constructor(private var value: Long) {
+ /**
+ * Gets the value of the atomic.
+ */
+ public actual fun load(): Long = value
+
+ /**
+ * Sets the value of the atomic to the [new value][newValue].
+ */
+ public actual fun store(newValue: Long) { value = newValue }
+
+ /**
+ * Sets the value to the given [new value][newValue] and returns the old value.
+ */
+ public actual fun exchange(newValue: Long): Long {
+ val oldValue = value
+ value = newValue
+ return oldValue
+ }
+
+ /**
+ * Sets the value to the given [new value][newValue] if the current value equals the [expected value][expectedValue],
+ * returns true if the operation was successful and false only if the current value was not equal to the expected value.
+ *
+ * Comparison of values is done by value.
+ */
+ public actual fun compareAndSet(expected: Long, newValue: Long): Boolean {
+ if (value != expected) return false
+ value = newValue
+ return true
+ }
+
+ /**
+ * Sets the value to the given [new value][newValue] if the current value equals the [expected value][expected]
+ * and returns the old value in any case.
+ *
+ * Comparison of values is done by value.
+ */
+ public actual fun compareAndExchange(expected: Long, newValue: Long): Long {
+ val oldValue = value
+ if (oldValue == expected) {
+ value = newValue
+ }
+ return oldValue
+ }
+
+ /**
+ * Adds the [given value][delta] to the current value and returns the old value.
+ */
+ public actual fun fetchAndAdd(delta: Long): Long {
+ val oldValue = value
+ value += delta
+ return oldValue
+ }
+
+ /**
+ * Adds the [given value][delta] to the current value and returns the new value.
+ */
+ public actual fun addAndFetch(delta: Long): Long {
+ value += delta
+ return value
+ }
+
+ /**
+ * Increments the current value by one and returns the old value.
+ */
+ public actual fun fetchAndIncrement(): Long = value++
+
+ /**
+ * Increments the current value by one and returns the new value.
+ */
+ public actual fun incrementAndFetch(): Long = ++value
+
+ /**
+ * Decrements the current value by one and returns the new value.
+ */
+ public actual fun fetchAndDecrement(): Long = value--
+
+ /**
+ * Decrements the current value by one and returns the old value.
+ */
+ public actual fun decrementAndFetch(): Long = --value
+
+ /**
+ * Returns the string representation of the underlying [Long] value.
+ */
+ public actual override fun toString(): String = value.toString()
+}
+
+/**
+ * An [Boolean] value which provides API of the common [AtomicBoolean].
+ *
+ * Does not provide any atomicity guarantees since the WASM platform does not support multi-threading.
+ */
+public actual class AtomicBoolean public actual constructor(private var value: Boolean) {
+
+ /**
+ * Gets the value of the atomic.
+ */
+ public actual fun load(): Boolean = value
+
+ /**
+ * Sets the value of the atomic to the [new value][newValue].
+ */
+ public actual fun store(newValue: Boolean) { value = newValue }
+
+ /**
+ * Sets the value to the given [new value][newValue] and returns the old value.
+ */
+ public actual fun exchange(newValue: Boolean): Boolean {
+ val oldValue = value
+ value = newValue
+ return oldValue
+ }
+
+ /**
+ * Sets the value to the given [new value][newValue] if the current value equals the [expected value][expectedValue],
+ * returns true if the operation was successful and false only if the current value was not equal to the expected value.
+ *
+ * Comparison of values is done by value.
+ */
+ public actual fun compareAndSet(expected: Boolean, newValue: Boolean): Boolean {
+ if (value != expected) return false
+ value = newValue
+ return true
+ }
+
+ /**
+ * Sets the value to the given [new value][newValue] if the current value equals the [expected value][expected]
+ * and returns the old value in any case.
+ *
+ * Comparison of values is done by value.
+ */
+ public actual fun compareAndExchange(expected: Boolean, newValue: Boolean): Boolean {
+ val oldValue = value
+ if (oldValue == expected) {
+ value = newValue
+ }
+ return oldValue
+ }
+
+ /**
+ * Returns the string representation of the underlying [Boolean] value.
+ */
+ public actual override fun toString(): String = value.toString()
+}
+
+/**
+ * An object reference which provides API of the common [AtomicReference].
+ *
+ * Does not provide any atomicity guarantees since the WASM platform does not support multi-threading.
+ */
+public actual class AtomicReference<T> public actual constructor(private var value: T) {
+ /**
+ * Gets the value of the atomic.
+ */
+ public actual fun load(): T = value
+
+ /**
+ * Sets the value of the atomic to the [new value][newValue].
+ */
+ public actual fun store(newValue: T) { value = newValue }
+
+ /**
+ * Sets the value to the given [new value][newValue] and returns the old value.
+ */
+ public actual fun exchange(newValue: T): T {
+ val oldValue = value
+ value = newValue
+ return oldValue
+ }
+
+ /**
+ * Sets the value to the given [new value][newValue] if the current value equals the [expected value][expectedValue],
+ * returns true if the operation was successful and false only if the current value was not equal to the expected value.
+ *
+ * Comparison of values is done by value.
+ */
+ public actual fun compareAndSet(expected: T, newValue: T): Boolean {
+ if (value != expected) return false
+ value = newValue
+ return true
+ }
+
+ /**
+ * Sets the value to the given [new value][newValue] if the current value equals the [expected value][expected]
+ * and returns the old value in any case.
+ *
+ * Comparison of values is done by value.
+ */
+ public actual fun compareAndExchange(expected: T, newValue: T): T {
+ val oldValue = value
+ if (oldValue == expected) {
+ value = newValue
+ }
+ return oldValue
+ }
+
+ /**
+ * Returns the string representation of the underlying object.
+ */
+ public actual override fun toString(): String = value.toString()
+}
\ No newline at end of file
diff --git a/libraries/stdlib/wasm/stubs/atomics.kt b/libraries/stdlib/wasm/stubs/atomics.kt
deleted file mode 100644
index 988f84e..0000000
--- a/libraries/stdlib/wasm/stubs/atomics.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2010-2023 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.
- */
-
-package kotlin.concurrent
-
-// Only for compatibility with shared K/N stdlib code
-
-internal actual class AtomicReference<T> actual constructor(public actual var value: T) {
- public actual fun compareAndExchange(expected: T, newValue: T): T {
- if (value == expected) {
- val old = value
- value = newValue
- return old
- }
- return value
- }
- public actual fun compareAndSet(expected: T, newValue: T): Boolean {
- if (value == expected) {
- value = newValue
- return true
- }
- return false
- }
-}