Atomicfu is a multiplatform Kotlin compiler plugin and library for atomic operations across JVM, Native, JS, and Wasm platforms
—
Arrays of atomic values for bulk operations and indexed atomic access patterns.
Creates atomic arrays for different primitive and reference types.
/**
* Creates an atomic integer array of specified size
* @param size - Number of atomic integers in the array
* @returns AtomicIntArray instance with atomic integer elements
*/
class AtomicIntArray(size: Int)
/**
* Creates an atomic long array of specified size
* @param size - Number of atomic longs in the array
* @returns AtomicLongArray instance with atomic long elements
*/
class AtomicLongArray(size: Int)
/**
* Creates an atomic boolean array of specified size
* @param size - Number of atomic booleans in the array
* @returns AtomicBooleanArray instance with atomic boolean elements
*/
class AtomicBooleanArray(size: Int)
/**
* Creates an atomic reference array initialized with nulls
* @param size - Number of atomic references in the array
* @returns AtomicArray<T?> instance with atomic reference elements
*/
fun <T> atomicArrayOfNulls(size: Int): AtomicArray<T?>Usage Examples:
import kotlinx.atomicfu.*
// Create atomic arrays
val counters = AtomicIntArray(10)
val flags = AtomicBooleanArray(5)
val nodes = atomicArrayOfNulls<Node>(20)Array of atomic integers with indexed access.
class AtomicIntArray(size: Int) {
/** Gets the atomic integer at the specified index */
operator fun get(index: Int): AtomicInt
/** Index-based access to atomic integer elements */
operator fun set(index: Int, value: AtomicInt): Unit
}Usage Examples:
val counters = AtomicIntArray(10)
// Access elements
counters[0].value = 5
val oldValue = counters[1].getAndIncrement()
counters[2].compareAndSet(0, 42)
// Array operations with atomic elements
counters[3].update { it * 2 }
counters[4].loop { value ->
if (counters[4].compareAndSet(value, value + 1)) {
return@loop
}
}
// Bulk operations
for (i in 0 until 10) {
counters[i].incrementAndGet()
}Array of atomic longs with indexed access.
class AtomicLongArray(size: Int) {
/** Gets the atomic long at the specified index */
operator fun get(index: Int): AtomicLong
/** Index-based access to atomic long elements */
operator fun set(index: Int, value: AtomicLong): Unit
}Usage Examples:
val timers = AtomicLongArray(5)
// Large number operations
timers[0].value = System.currentTimeMillis()
timers[1].addAndGet(1000000000L)
// Update with validation
timers[2].update { currentTime ->
if (currentTime > 0) currentTime + 1000 else System.currentTimeMillis()
}Array of atomic booleans with indexed access.
class AtomicBooleanArray(size: Int) {
/** Gets the atomic boolean at the specified index */
operator fun get(index: Int): AtomicBoolean
/** Index-based access to atomic boolean elements */
operator fun set(index: Int, value: AtomicBoolean): Unit
}Usage Examples:
val statusFlags = AtomicBooleanArray(10)
// Flag operations
statusFlags[0].compareAndSet(false, true)
val wasEnabled = statusFlags[1].getAndSet(false)
// Bulk flag operations
for (i in 0 until 10) {
statusFlags[i].update { !it } // toggle all flags
}
// Conditional operations
statusFlags[2].loop { current ->
if (!current && statusFlags[2].compareAndSet(false, true)) {
return@loop // successfully acquired flag
}
}Generic array of atomic references with indexed access.
class AtomicArray<T>(size: Int) {
/** Gets the atomic reference at the specified index */
operator fun get(index: Int): AtomicRef<T>
/** Index-based access to atomic reference elements */
operator fun set(index: Int, value: AtomicRef<T>): Unit
}Usage Examples:
data class Task(val id: Int, val name: String)
val tasks = atomicArrayOfNulls<Task>(10)
// Reference operations
tasks[0].value = Task(1, "First Task")
val oldTask = tasks[1].getAndSet(Task(2, "Second Task"))
// Lock-free data structure operations
fun addTask(index: Int, task: Task): Boolean {
return tasks[index].compareAndSet(null, task)
}
fun removeTask(index: Int): Task? {
return tasks[index].getAndSet(null)
}
// Atomic updates
tasks[2].update { currentTask ->
currentTask?.copy(name = "${currentTask.name} - Updated")
}
// Complex array operations
fun findAndUpdateTask(predicate: (Task?) -> Boolean, update: (Task?) -> Task?): Boolean {
for (i in 0 until 10) {
tasks[i].loop { current ->
if (predicate(current)) {
val newValue = update(current)
if (tasks[i].compareAndSet(current, newValue)) {
return true
}
} else {
return@loop
}
}
}
return false
}Common patterns for working with atomic arrays.
Usage Examples:
// Pattern 1: Parallel counters
val workerCounters = AtomicIntArray(Runtime.getRuntime().availableProcessors())
fun incrementWorkerCounter(workerId: Int) {
workerCounters[workerId].incrementAndGet()
}
// Pattern 2: Lock-free ring buffer
class LockFreeRingBuffer<T>(capacity: Int) {
private val buffer = atomicArrayOfNulls<T>(capacity)
private val head = atomic(0)
private val tail = atomic(0)
fun offer(item: T): Boolean {
val currentTail = tail.value
val nextTail = (currentTail + 1) % buffer.size
return if (nextTail != head.value) {
buffer[currentTail].compareAndSet(null, item) &&
tail.compareAndSet(currentTail, nextTail)
} else {
false // buffer full
}
}
fun poll(): T? {
val currentHead = head.value
return if (currentHead != tail.value) {
val item = buffer[currentHead].getAndSet(null)
head.compareAndSet(currentHead, (currentHead + 1) % buffer.size)
item
} else {
null // buffer empty
}
}
}
// Pattern 3: Atomic bit set
class AtomicBitSet(size: Int) {
private val bits = AtomicBooleanArray(size)
fun set(index: Int): Boolean = bits[index].getAndSet(true)
fun clear(index: Int): Boolean = bits[index].getAndSet(false)
fun get(index: Int): Boolean = bits[index].value
fun setIf(index: Int, condition: Boolean): Boolean {
return if (condition) bits[index].compareAndSet(false, true) else false
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-jetbrains-kotlin--kotlin-atomicfu-compiler-plugin