AtomicFU JVM-specific artifact providing idiomatic and efficient atomic operations optimized for the JVM platform using AtomicXxxFieldUpdater or VarHandle.
—
Array-based atomic data structures for managing collections of atomic values with indexed access patterns.
Creates arrays of atomic references initialized with null values.
/**
* Creates array of AtomicRef<T> of specified size, where each element is initialized with null value
*/
fun <T> atomicArrayOfNulls(size: Int): AtomicArray<T?>
class AtomicArray<T> {
/** Array size property */
val size: Int
/** Get AtomicRef<T?> at index */
operator fun get(index: Int): AtomicRef<T?>
}Usage Examples:
import kotlinx.atomicfu.*
class ConcurrentCache<T> {
private val cache = atomicArrayOfNulls<T>(100)
fun put(index: Int, value: T) {
if (index in 0 until cache.size) {
cache[index].value = value
}
}
fun get(index: Int): T? {
return if (index in 0 until cache.size) {
cache[index].value
} else null
}
fun compareAndSet(index: Int, expected: T?, newValue: T?): Boolean {
return if (index in 0 until cache.size) {
cache[index].compareAndSet(expected, newValue)
} else false
}
fun clear() {
for (i in 0 until cache.size) {
cache[i].value = null
}
}
}Creates arrays of atomic integers initialized with zero values.
/**
* Creates a new array of AtomicInt values of the specified size, where each element is initialized with 0
*/
class AtomicIntArray(size: Int) {
/** Array size property */
val size: Int
/** Get AtomicInt at index */
operator fun get(index: Int): AtomicInt
}Usage Examples:
import kotlinx.atomicfu.*
class ConcurrentCounters {
private val counters = AtomicIntArray(10)
fun increment(index: Int): Int {
return if (index in 0 until counters.size) {
counters[index].incrementAndGet()
} else 0
}
fun add(index: Int, delta: Int): Int {
return if (index in 0 until counters.size) {
counters[index].addAndGet(delta)
} else 0
}
fun get(index: Int): Int {
return if (index in 0 until counters.size) {
counters[index].value
} else 0
}
fun reset(index: Int) {
if (index in 0 until counters.size) {
counters[index].value = 0
}
}
fun getTotalCount(): Int {
var total = 0
for (i in 0 until counters.size) {
total += counters[i].value
}
return total
}
}Creates arrays of atomic longs initialized with zero values.
/**
* Creates a new array of AtomicLong values of the specified size, where each element is initialized with 0L
*/
class AtomicLongArray(size: Int) {
/** Array size property */
val size: Int
/** Get AtomicLong at index */
operator fun get(index: Int): AtomicLong
}Usage Examples:
import kotlinx.atomicfu.*
class MetricsCollector {
private val metrics = AtomicLongArray(50)
fun recordMetric(metricId: Int, value: Long) {
if (metricId in 0 until metrics.size) {
metrics[metricId].addAndGet(value)
}
}
fun incrementMetric(metricId: Int): Long {
return if (metricId in 0 until metrics.size) {
metrics[metricId].incrementAndGet()
} else 0L
}
fun getMetric(metricId: Int): Long {
return if (metricId in 0 until metrics.size) {
metrics[metricId].value
} else 0L
}
fun resetMetric(metricId: Int) {
if (metricId in 0 until metrics.size) {
metrics[metricId].value = 0L
}
}
fun getSnapshot(): LongArray {
val snapshot = LongArray(metrics.size)
for (i in 0 until metrics.size) {
snapshot[i] = metrics[i].value
}
return snapshot
}
}Creates arrays of atomic booleans initialized with false values.
/**
* Creates a new array of AtomicBoolean values of the specified size, where each element is initialized with false
*/
class AtomicBooleanArray(size: Int) {
/** Array size property */
val size: Int
/** Get AtomicBoolean at index */
operator fun get(index: Int): AtomicBoolean
}Usage Examples:
import kotlinx.atomicfu.*
class ConcurrentFlags {
private val flags = AtomicBooleanArray(32)
fun setFlag(index: Int): Boolean {
return if (index in 0 until flags.size) {
flags[index].getAndSet(true)
} else false
}
fun clearFlag(index: Int): Boolean {
return if (index in 0 until flags.size) {
flags[index].getAndSet(false)
} else false
}
fun toggleFlag(index: Int): Boolean {
if (index in 0 until flags.size) {
val flag = flags[index]
while (true) {
val current = flag.value
if (flag.compareAndSet(current, !current)) {
return !current
}
}
}
return false
}
fun isSet(index: Int): Boolean {
return if (index in 0 until flags.size) {
flags[index].value
} else false
}
fun countSetFlags(): Int {
var count = 0
for (i in 0 until flags.size) {
if (flags[i].value) count++
}
return count
}
fun allSet(): Boolean {
for (i in 0 until flags.size) {
if (!flags[i].value) return false
}
return true
}
fun anySet(): Boolean {
for (i in 0 until flags.size) {
if (flags[i].value) return true
}
return false
}
}Atomic arrays are commonly used to build lock-free data structures:
import kotlinx.atomicfu.*
class LockFreeQueue<T>(capacity: Int) {
private val buffer = atomicArrayOfNulls<T>(capacity)
private val head = atomic(0)
private val tail = atomic(0)
fun offer(item: T): Boolean {
while (true) {
val currentTail = tail.value
val nextTail = (currentTail + 1) % buffer.size
if (nextTail == head.value) {
// Queue is full
return false
}
if (buffer[currentTail].compareAndSet(null, item)) {
tail.compareAndSet(currentTail, nextTail)
return true
}
}
}
fun poll(): T? {
while (true) {
val currentHead = head.value
val item = buffer[currentHead].value
if (item == null) {
// Queue is empty
return null
}
if (buffer[currentHead].compareAndSet(item, null)) {
head.compareAndSet(currentHead, (currentHead + 1) % buffer.size)
return item
}
}
}
}import kotlinx.atomicfu.*
class WorkDistributor<T>(private val tasks: List<T>) {
private val processed = AtomicBooleanArray(tasks.size)
private val results = atomicArrayOfNulls<String>(tasks.size)
private val nextIndex = atomic(0)
fun getNextTask(): Pair<Int, T>? {
while (true) {
val index = nextIndex.value
if (index >= tasks.size) return null
if (nextIndex.compareAndSet(index, index + 1)) {
return index to tasks[index]
}
}
}
fun completeTask(index: Int, result: String) {
results[index].value = result
processed[index].value = true
}
fun isComplete(): Boolean {
for (i in 0 until processed.size) {
if (!processed[i].value) return false
}
return true
}
fun getResults(): List<String?> {
return (0 until results.size).map { results[it].value }
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-jetbrains-kotlinx--atomicfu-jvm