0
# Atomic Operations
1
2
Core atomic operations for thread-safe programming with compare-and-swap, arithmetic operations, and high-level update patterns.
3
4
## Capabilities
5
6
### Factory Functions
7
8
Creates atomic wrappers for different primitive and reference types.
9
10
```kotlin { .api }
11
/**
12
* Creates an atomic integer wrapper
13
* @param value - Initial integer value
14
* @returns AtomicInt instance for atomic integer operations
15
*/
16
fun atomic(value: Int): AtomicInt
17
18
/**
19
* Creates an atomic long wrapper
20
* @param value - Initial long value
21
* @returns AtomicLong instance for atomic long operations
22
*/
23
fun atomic(value: Long): AtomicLong
24
25
/**
26
* Creates an atomic boolean wrapper
27
* @param value - Initial boolean value
28
* @returns AtomicBoolean instance for atomic boolean operations
29
*/
30
fun atomic(value: Boolean): AtomicBoolean
31
32
/**
33
* Creates an atomic reference wrapper for any type
34
* @param value - Initial reference value
35
* @returns AtomicRef<T> instance for atomic reference operations
36
*/
37
fun <T> atomic(value: T): AtomicRef<T>
38
39
/**
40
* Creates an atomic integer wrapper with tracing support
41
* @param value - Initial integer value
42
* @param trace - Trace instance for debugging atomic operations
43
* @returns AtomicInt instance for atomic integer operations with tracing
44
*/
45
fun atomic(value: Int, trace: Trace): AtomicInt
46
47
/**
48
* Creates an atomic long wrapper with tracing support
49
* @param value - Initial long value
50
* @param trace - Trace instance for debugging atomic operations
51
* @returns AtomicLong instance for atomic long operations with tracing
52
*/
53
fun atomic(value: Long, trace: Trace): AtomicLong
54
55
/**
56
* Creates an atomic boolean wrapper with tracing support
57
* @param value - Initial boolean value
58
* @param trace - Trace instance for debugging atomic operations
59
* @returns AtomicBoolean instance for atomic boolean operations with tracing
60
*/
61
fun atomic(value: Boolean, trace: Trace): AtomicBoolean
62
63
/**
64
* Creates an atomic reference wrapper with tracing support
65
* @param value - Initial reference value
66
* @param trace - Trace instance for debugging atomic operations
67
* @returns AtomicRef<T> instance for atomic reference operations with tracing
68
*/
69
fun <T> atomic(value: T, trace: Trace): AtomicRef<T>
70
```
71
72
**Usage Examples:**
73
74
```kotlin
75
import kotlinx.atomicfu.*
76
77
// Create atomic values
78
val counter = atomic(0)
79
val flag = atomic(false)
80
val name = atomic<String?>(null)
81
val obj = atomic(MyObject())
82
```
83
84
### AtomicInt Operations
85
86
Atomic operations for integer values with arithmetic support.
87
88
```kotlin { .api }
89
interface AtomicInt {
90
/** Current integer value */
91
var value: Int
92
93
/** Atomically sets the value with lazy semantics */
94
fun lazySet(newValue: Int): Unit
95
96
/** Atomically compares current value with expected and sets to update if equal */
97
fun compareAndSet(expect: Int, update: Int): Boolean
98
99
/** Atomically sets to newValue and returns the old value */
100
fun getAndSet(newValue: Int): Int
101
102
/** Atomically increments and returns the old value */
103
fun getAndIncrement(): Int
104
105
/** Atomically increments and returns the new value */
106
fun incrementAndGet(): Int
107
108
/** Atomically decrements and returns the old value */
109
fun getAndDecrement(): Int
110
111
/** Atomically decrements and returns the new value */
112
fun decrementAndGet(): Int
113
114
/** Atomically adds delta and returns the old value */
115
fun getAndAdd(delta: Int): Int
116
117
/** Atomically adds delta and returns the new value */
118
fun addAndGet(delta: Int): Int
119
120
/** Loops until the action completes successfully */
121
fun loop(action: (Int) -> Unit): Nothing
122
123
/** Updates the value using the transform function */
124
fun update(function: (Int) -> Int): Unit
125
126
/** Updates the value and returns the new value */
127
fun updateAndGet(function: (Int) -> Int): Int
128
129
/** Updates the value and returns the old value */
130
fun getAndUpdate(function: (Int) -> Int): Int
131
}
132
```
133
134
**Usage Examples:**
135
136
```kotlin
137
val counter = atomic(0)
138
139
// Basic operations
140
counter.value = 5
141
counter.lazySet(10)
142
counter.compareAndSet(10, 20) // true
143
144
// Arithmetic operations
145
val oldValue = counter.getAndIncrement() // returns 20, sets to 21
146
val newValue = counter.incrementAndGet() // returns 22
147
148
// High-level operations
149
counter.update { it * 2 } // doubles the current value
150
val result = counter.updateAndGet { it + 5 } // adds 5 and returns new value
151
```
152
153
### AtomicLong Operations
154
155
Atomic operations for long values with arithmetic support.
156
157
```kotlin { .api }
158
interface AtomicLong {
159
/** Current long value */
160
var value: Long
161
162
/** Atomically sets the value with lazy semantics */
163
fun lazySet(newValue: Long): Unit
164
165
/** Atomically compares current value with expected and sets to update if equal */
166
fun compareAndSet(expect: Long, update: Long): Boolean
167
168
/** Atomically sets to newValue and returns the old value */
169
fun getAndSet(newValue: Long): Long
170
171
/** Atomically increments and returns the old value */
172
fun getAndIncrement(): Long
173
174
/** Atomically increments and returns the new value */
175
fun incrementAndGet(): Long
176
177
/** Atomically decrements and returns the old value */
178
fun getAndDecrement(): Long
179
180
/** Atomically decrements and returns the new value */
181
fun decrementAndGet(): Long
182
183
/** Atomically adds delta and returns the old value */
184
fun getAndAdd(delta: Long): Long
185
186
/** Atomically adds delta and returns the new value */
187
fun addAndGet(delta: Long): Long
188
189
/** Loops until the action completes successfully */
190
fun loop(action: (Long) -> Unit): Nothing
191
192
/** Updates the value using the transform function */
193
fun update(function: (Long) -> Long): Unit
194
195
/** Updates the value and returns the new value */
196
fun updateAndGet(function: (Long) -> Long): Long
197
198
/** Updates the value and returns the old value */
199
fun getAndUpdate(function: (Long) -> Long): Long
200
}
201
```
202
203
**Usage Examples:**
204
205
```kotlin
206
val largeCounter = atomic(5000000000L)
207
208
// Large number operations
209
largeCounter.addAndGet(1000000000L)
210
largeCounter.update { value ->
211
if (value > Long.MAX_VALUE / 2) Long.MAX_VALUE else value * 2
212
}
213
```
214
215
### AtomicBoolean Operations
216
217
Atomic operations for boolean values.
218
219
```kotlin { .api }
220
interface AtomicBoolean {
221
/** Current boolean value */
222
var value: Boolean
223
224
/** Atomically sets the value with lazy semantics */
225
fun lazySet(newValue: Boolean): Unit
226
227
/** Atomically compares current value with expected and sets to update if equal */
228
fun compareAndSet(expect: Boolean, update: Boolean): Boolean
229
230
/** Atomically sets to newValue and returns the old value */
231
fun getAndSet(newValue: Boolean): Boolean
232
233
/** Loops until the action completes successfully */
234
fun loop(action: (Boolean) -> Unit): Nothing
235
236
/** Updates the value using the transform function */
237
fun update(function: (Boolean) -> Boolean): Unit
238
239
/** Updates the value and returns the new value */
240
fun updateAndGet(function: (Boolean) -> Boolean): Boolean
241
242
/** Updates the value and returns the old value */
243
fun getAndUpdate(function: (Boolean) -> Boolean): Boolean
244
}
245
```
246
247
**Usage Examples:**
248
249
```kotlin
250
val flag = atomic(false)
251
252
// Toggle operations
253
val wasSet = flag.getAndSet(true) // returns false, sets to true
254
flag.update { !it } // toggles the value
255
256
// Conditional operations
257
if (flag.compareAndSet(false, true)) {
258
// Flag was false and is now set to true
259
performAction()
260
}
261
```
262
263
### AtomicRef Operations
264
265
Atomic operations for reference types.
266
267
```kotlin { .api }
268
interface AtomicRef<T> {
269
/** Current reference value */
270
var value: T
271
272
/** Atomically sets the value with lazy semantics */
273
fun lazySet(newValue: T): Unit
274
275
/** Atomically compares current value with expected and sets to update if equal */
276
fun compareAndSet(expect: T, update: T): Boolean
277
278
/** Atomically sets to newValue and returns the old value */
279
fun getAndSet(newValue: T): T
280
281
/** Loops until the action completes successfully */
282
fun loop(action: (T) -> Unit): Nothing
283
284
/** Updates the value using the transform function */
285
fun update(function: (T) -> T): Unit
286
287
/** Updates the value and returns the new value */
288
fun updateAndGet(function: (T) -> T): T
289
290
/** Updates the value and returns the old value */
291
fun getAndUpdate(function: (T) -> T): T
292
}
293
```
294
295
**Usage Examples:**
296
297
```kotlin
298
data class Node(val value: Int, val next: Node?)
299
300
val head = atomic<Node?>(null)
301
302
// Atomic reference operations
303
val oldHead = head.getAndSet(Node(1, null))
304
head.update { current -> Node(2, current) } // prepend to list
305
306
// Lock-free data structure example
307
fun push(item: Int) {
308
head.update { current -> Node(item, current) }
309
}
310
311
fun pop(): Int? {
312
return head.updateAndGet { current ->
313
current?.next
314
}?.value
315
}
316
```
317
318
### Trace API
319
320
Debugging and tracing support for atomic operations.
321
322
```kotlin { .api }
323
/**
324
* Trace class for debugging atomic operations
325
*/
326
class Trace {
327
/** Creates a default trace */
328
constructor()
329
330
/** Creates a trace with specified capacity */
331
constructor(capacity: Int)
332
333
/** Creates a trace with custom format */
334
constructor(format: TraceFormat)
335
336
/** Creates a trace with capacity and format */
337
constructor(capacity: Int, format: TraceFormat)
338
339
/** Creates a named trace for better identification */
340
fun named(name: String): Trace
341
342
/** Appends a trace message */
343
fun append(message: String)
344
345
/** Appends a trace message with value */
346
fun append(message: String, value: Any)
347
348
/** Appends a trace message with ID and value */
349
fun append(id: Any, value: Any)
350
351
/** Appends a trace message with ID, value, and description */
352
fun append(id: Any, value: Any, description: String)
353
354
/** Function call operator for tracing */
355
operator fun invoke(message: () -> String)
356
}
357
358
/**
359
* Trace format for customizing trace output
360
*/
361
class TraceFormat(val formatter: (id: Any, text: String) -> String)
362
```
363
364
**Usage Examples:**
365
366
```kotlin
367
// Basic tracing
368
val trace = Trace()
369
val counter = atomic(0, trace)
370
371
trace { "Initial value: ${counter.value}" }
372
counter.incrementAndGet()
373
trace { "After increment: ${counter.value}" }
374
375
// Named trace
376
val namedTrace = Trace().named("worker-1")
377
val workerCounter = atomic(0, namedTrace)
378
379
// Custom format
380
val customTrace = Trace(format = TraceFormat { id, text -> "[$id]: $text" })
381
val formattedCounter = atomic(0, customTrace)
382
383
// Trace with capacity
384
val limitedTrace = Trace(10) // Only keeps last 10 entries
385
```
386
387
### Delegated Properties
388
389
Atomic values can be used as delegated properties for seamless integration.
390
391
```kotlin { .api }
392
/**
393
* Atomic values support property delegation
394
* Allows using atomic values as backing properties with automatic get/set delegation
395
*/
396
val atomicValue = atomic(initialValue)
397
var property: T by atomicValue
398
```
399
400
**Usage Examples:**
401
402
```kotlin
403
// Delegated property with atomic backing
404
private val _counter = atomic(0)
405
var counter: Int by _counter
406
407
// Usage is transparent
408
counter = 5 // Calls _counter.value = 5
409
val value = counter // Calls _counter.value
410
411
// Object-level delegated properties
412
object GlobalState {
413
private val _isEnabled = atomic(false)
414
var isEnabled: Boolean by _isEnabled
415
416
private val _name = atomic<String?>(null)
417
var name: String? by _name
418
}
419
420
// Class-level delegated properties
421
class Configuration {
422
var timeout: Int by atomic(30)
423
var retryCount: Int by atomic(3)
424
var isDebugMode: Boolean by atomic(false)
425
}
426
427
// Top-level delegated properties
428
private val _globalCounter = atomic(0)
429
var globalCounter: Int by _globalCounter
430
431
### Usage Constraints and Best Practices
432
433
Atomicfu has specific requirements and constraints for proper usage and compiler transformation.
434
435
#### **Visibility Constraints**
436
437
Atomic properties must follow specific visibility rules for compiler transformation to work correctly.
438
439
```kotlin
440
// ✅ Correct: Private atomic properties
441
class Counter {
442
private val count = atomic(0)
443
444
fun increment() = count.incrementAndGet()
445
fun get() = count.value
446
}
447
448
// ✅ Correct: Internal atomic properties
449
class InternalCounter {
450
internal val count = atomic(0)
451
}
452
453
// ❌ Incorrect: Public atomic properties are forbidden
454
class PublicCounter {
455
val count = atomic(0) // Compiler error: PUBLIC_ATOMICS_ARE_FORBIDDEN
456
}
457
458
// ❌ Incorrect: @PublishedApi atomic properties are forbidden
459
class ApiCounter {
460
@PublishedApi
461
internal val count = atomic(0) // Compiler error: PUBLISHED_API_ATOMICS_ARE_FORBIDDEN
462
}
463
```
464
465
#### **Property Declaration Constraints**
466
467
Atomic properties should be declared as `val`, not `var`, for proper transformation.
468
469
```kotlin
470
// ✅ Correct: val declaration
471
class Counter {
472
private val count = atomic(0)
473
}
474
475
// ❌ Incorrect: var declaration
476
class MutableCounter {
477
private var count = atomic(0) // Compiler error: ATOMIC_PROPERTIES_SHOULD_BE_VAL
478
}
479
```
480
481
#### **Usage Pattern Constraints**
482
483
Atomic operations must be called directly on atomic properties, not through intermediate variables.
484
485
```kotlin
486
class Counter {
487
private val count = atomic(0)
488
489
// ✅ Correct: Direct invocation
490
fun increment() = count.incrementAndGet()
491
492
// ❌ Incorrect: Local variable assignment
493
fun incrementWrong() {
494
val localRef = count // This breaks transformation
495
return localRef.incrementAndGet()
496
}
497
498
// ✅ Correct: Simple expressions in parameters
499
fun addValue(delta: Int) = count.addAndGet(delta)
500
501
// ❌ Incorrect: Complex expressions in atomic operations
502
fun complexOperation() {
503
count.compareAndSet(
504
computeExpected(), // Complex expression - avoid
505
computeNew() // Complex expression - avoid
506
)
507
}
508
}
509
```
510
511
#### **Platform-Specific Behavior**
512
513
Different platforms have different transformation behaviors and performance characteristics.
514
515
**JVM Platform:**
516
- Transforms to `java.util.concurrent.atomic.*` classes
517
- Best performance due to native JVM atomic support
518
- Full feature support including all operations
519
520
**JavaScript Platform:**
521
- Transforms to runtime functions with lock-free algorithms
522
- Uses `atomicfu_*` runtime functions for operations
523
- Good performance but not as optimal as JVM
524
525
**Native Platform:**
526
- Uses Kotlin/Native atomic intrinsics
527
- Direct memory operations for best native performance
528
- Platform-specific atomic implementations
529
530
**WebAssembly Platform:**
531
- Runtime implementations adapted for Wasm
532
- Performance depends on Wasm runtime capabilities
533
534
#### **Diagnostic Messages**
535
536
The compiler provides specific error messages for improper usage:
537
538
- **`PUBLIC_ATOMICS_ARE_FORBIDDEN`**: Atomic properties cannot be public
539
- **`PUBLISHED_API_ATOMICS_ARE_FORBIDDEN`**: Atomic properties cannot use @PublishedApi
540
- **`ATOMIC_PROPERTIES_SHOULD_BE_VAL`**: Atomic properties should be declared as val
541
542
#### **Recommended Patterns**
543
544
**Pattern 1: Encapsulated Atomic State**
545
```kotlin
546
class ThreadSafeCounter {
547
private val _count = atomic(0)
548
549
val count: Int get() = _count.value
550
551
fun increment(): Int = _count.incrementAndGet()
552
fun decrement(): Int = _count.decrementAndGet()
553
}
554
```
555
556
**Pattern 2: Delegated Properties for Public Access**
557
```kotlin
558
class PublicCounter {
559
private val _count = atomic(0)
560
var count: Int by _count // Public access through delegation
561
562
fun atomicIncrement() = _count.incrementAndGet()
563
}
564
```
565
566
**Pattern 3: Lock-Free Data Structures**
567
```kotlin
568
class LockFreeStack<T> {
569
private val top = atomic<Node<T>?>(null)
570
571
private data class Node<T>(val value: T, val next: Node<T>?)
572
573
fun push(value: T) {
574
top.update { current -> Node(value, current) }
575
}
576
577
fun pop(): T? {
578
return top.updateAndGet { current -> current?.next }?.value
579
}
580
}
581
```