or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

atomic-arrays.mdatomic-operations.mdindex.mdlock-free-synchronization.mdplugin-configuration.md

atomic-operations.mddocs/

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

```