# AtomicFU 

[![JetBrains incubator project](https://jb.gg/badges/incubator.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
[![GitHub license](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](https://www.apache.org/licenses/LICENSE-2.0)
[![Download](https://api.bintray.com/packages/kotlin/kotlinx/kotlinx.atomicfu/images/download.svg) ](https://bintray.com/kotlin/kotlinx/kotlinx.atomicfu/_latestVersion)

The idiomatic way to use atomic operations in Kotlin. 

* Code it like `AtomicReference/Int/Long`, but run it in production efficiently as `AtomicXxxFieldUpdater` on Kotlin/JVM 
  and as plain unboxed values on Kotlin/JS. 
* Use Kotlin-specific extensions (e.g. inline `updateAndGet` and `getAndUpdate` functions).
* Compile-time dependency only (no runtime dependencies).
  * Post-compilation bytecode transformer that declares all the relevant field updaters for you on [Kotlin/JVM](#jvm).
  * Post-compilation JavaScript files transformer on [Kotlin/JS](#js).
* Multiplatform: 
  * [Kotlin/Native](#native) is supported.
  * However, Kotlin/Native works as library dependency at the moment (unlike Kotlin/JVM and Kotlin/JS).
  * This enables writing [common](#common) Kotlin code with atomics that compiles for JVM, JS, and Native.
* [Gradle](#gradle-build-setup) for all platforms and [Maven](#maven-build-setup) for JVM are supported.  
* [Additional features](#additional-features) include:
  * [JDK9 VarHandle](#varhandles-with-java-9).
  * [Arrays of atomic values](#arrays-of-atomic-values).
  * [User-defined extensions on atomics](#user-defined-extensions-on-atomics)
  * [Locks](#locks)
  * [Testing of lock-free data structures](#testing-lock-free-data-structures-on-jvm).
  * [Tracing operations](#tracing-operations)

## Example

Let us declare a `top` variable for a lock-free stack implementation:

```kotlin
import kotlinx.atomicfu.* // import top-level functions from kotlinx.atomicfu

private val top = atomic(null) 
```

Use `top.value` to perform volatile reads and writes:

```kotlin
fun isEmpty() = top.value == null  // volatile read
fun clear() { top.value = null }   // volatile write
``` 

Use `compareAndSet` function directly:

```kotlin
if (top.compareAndSet(expect, update)) ... 
```

Use higher-level looping primitives (inline extensions), for example:

```kotlin
top.loop { cur ->   // while(true) loop that volatile-reads current value 
   ...
}
```

Use high-level `update`, `updateAndGet`, and `getAndUpdate`, 
when possible, for idiomatic lock-free code, for example:

```kotlin
fun push(v: Value) = top.update { cur -> Node(v, cur) }
fun pop(): Value? = top.getAndUpdate { cur -> cur?.next } ?.value
```

Declare atomic integers and longs using type inference:

```kotlin
val myInt = atomic(0)    // note: integer initial value
val myLong = atomic(0L)  // note: long initial value   
```

Integer and long atomics provide all the usual `getAndIncrement`, `incrementAndGet`, `getAndAdd`, `addAndGet`, and etc
operations. They can be also atomically modified via `+=` and `-=` operators.

## Dos and Don'ts

* Declare atomic variables as `private val` or `internal val`. You can use just (public) `val`, 
  but make sure they are not directly accessed outside of your Kotlin module (outside of the source set).
  Access to the atomic variable itself shall be encapsulated.
* Only simple operations on atomic variables _directly_ are supported. 
  * Do not read references on atomic variables into local variables,
    e.g. `top.compareAndSet(...)` is Ok, while `val tmp = top; tmp...` is not. 
  * Do not leak references on atomic variables in other way (return, pass as params, etc). 
* Do not introduce complex data flow in parameters to atomic variable operations, 
  i.e. `top.value = complex_expression` and `top.compareAndSet(cur, complex_expression)` are not supported 
  (more specifically, `complex_expression` should not have branches in its compiled representation).
  Extract `complex_expression` into a variable when needed.
* Use the following convention if you need to expose the value of atomic property to the public:

```kotlin
private val _foo = atomic(initial) // private atomic, convention is to name it with leading underscore
public var foo: T by _foo            // public delegated property (val/var)
```  

## Gradle build setup

Building with Gradle is supported for all platforms.

### JVM

You will need Gradle 4.10 or later.
Add and apply AtomicFU plugin. It adds all the corresponding dependencies
and transformations automatically. 
See [additional configuration](#additional-configuration) if that needs tweaking.

```groovy
buildscript {
    ext.atomicfu_version = '0.16.0'

    dependencies {
        classpath "org.jetbrains.kotlinx:atomicfu-gradle-plugin:$atomicfu_version"
    }
}

apply plugin: 'kotlinx-atomicfu'
```

### JS 

Configure add apply plugin just like for [JVM](#jvm). 

### Native

This library is available for Kotlin/Native (`atomicfu-native`).
Kotlin/Native uses Gradle metadata and needs Gradle version 5.3 or later.
See [Gradle Metadata 1.0 announcement](https://blog.gradle.org/gradle-metadata-1.0) for more details.
Apply the corresponding plugin just like for [JVM](#jvm). 

Atomic references for Kotlin/Native are based on 
[FreezableAtomicReference](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.native.concurrent/-freezable-atomic-reference/-init-.html)
and every reference that is stored to the previously 
[frozen](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.native.concurrent/freeze.html) 
(shared with another thread) atomic is automatically frozen, too.

Since Kotlin/Native does not generally provide binary compatibility between versions, 
you should use the same version of Kotlin compiler as was used to build AtomicFU. 
See [gradle.properties](gradle.properties) in AtomicFU project for its `kotlin_version`.

### Common

If you write a common code that should get compiled or different platforms, add `org.jetbrains.kotlinx:atomicfu-common`
to your common code dependencies or apply `kotlinx-atomicfu` plugin that adds this dependency automatically:

```groovy
dependencies {
    compile "org.jetbrains.kotlinx:atomicfu-common:$atomicfu_version"
}
```

### Additional configuration

There are the following additional parameters (with their defaults):

```groovy
atomicfu {
  dependenciesVersion = '0.16.0' // set to null to turn-off auto dependencies
  transformJvm = true // set to false to turn off JVM transformation
  transformJs = true // set to false to turn off JS transformation
  variant = "FU" // JVM transformation variant: FU,VH, or BOTH 
  verbose = false // set to true to be more verbose  
}
```

## Maven build setup

Declare AtomicFU version:

```xml

     0.16.0
 
```

Declare _provided_ dependency on the AtomicFU library 
(the users of the resulting artifact will not have a dependency on AtomicFU library):

```xml

    
        org.jetbrains.kotlinx
        atomicfu
        ${atomicfu.version}
        provided
    

```

Configure build steps so that Kotlin compiler puts classes into a different `classes-pre-atomicfu` directory,
which is then transformed to a regular `classes` directory to be used later by tests and delivery.

```xml

    
        
        
            org.jetbrains.kotlin
            kotlin-maven-plugin
            ${kotlin.version}
            
                
                    compile
                    compile
                    
                        compile
                    
                    
                        ${project.build.directory}/classes-pre-atomicfu
                        
                        FU  
                    
                
            
        
        
        
            org.jetbrains.kotlinx
            atomicfu-maven-plugin
            ${atomicfu.version}
            
                
                    
                        transform
                    
                    
                        ${project.build.directory}/classes-pre-atomicfu
                    
                
            
        
    

```

## Additional features

AtomicFU provides some additional features that you can optionally use.

### VarHandles with Java 9

AtomicFU can produce code that uses Java 9 
[VarHandle](https://docs.oracle.com/javase/9/docs/api/java/lang/invoke/VarHandle.html)
instead of `AtomicXxxFieldUpdater`. Configure transformation `variant` in Gradle build file:
 
```groovy
atomicfu {
    variant = "VH"
}
``` 
 
It can also create [JEP 238](https://openjdk.java.net/jeps/238) multi-release jar file with both
`AtomicXxxFieldUpdater` for JDK<=8 and `VarHandle` for for JDK9+ if you 
set `variant` to `"BOTH"`.

### Arrays of atomic values

You can declare arrays of all supported atomic value types. 
By default arrays are transformed into the corresponding `java.util.concurrent.atomic.Atomic*Array` instances.

If you configure `variant = "VH"` an array will be transformed to plain array using 
[VarHandle](https://docs.oracle.com/javase/9/docs/api/java/lang/invoke/VarHandle.html) to support atomic operations.
  
```kotlin
val a = atomicArrayOfNulls(size) // similar to Array constructor

val x = a[i].value // read value
a[i].value = x // set value
a[i].compareAndSet(expect, update) // do atomic operations
```

### User-defined extensions on atomics

You can define you own extension functions on `AtomicXxx` types but they must be `inline` and they cannot
be public and be used outside of the module they are defined in. For example:

```kotlin
@Suppress("NOTHING_TO_INLINE")
private inline fun AtomicBoolean.tryAcquire(): Boolean = compareAndSet(false, true)
```

### Locks

This project includes `kotlinx.atomicfu.locks` package providing multiplatform locking primitives that
require no additional runtime dependencies on Kotlin/JVM and Kotlin/JS with a library implementation for 
Kotlin/Native.

* `SynchronizedObject` is designed for inheritance. You write `class MyClass : SynchronizedObject()` and then 
use `synchronized(instance) { ... }` extension function similarly to the 
[synchronized](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/synchronized.html)
function from the standard library that is available for JVM. The `SynchronizedObject` superclass gets erased
(transformed to `Any`) on JVM and JS, with `synchronized` leaving no trace in the code on JS and getting 
replaced with built-in monitors for locking on JVM.

* `ReentrantLock` is designed for delegation. You write `val lock = reentrantLock()` to construct its instance and
use `lock`/`tryLock`/`unlock` functions or `lock.withLock { ... }` extension function similarly to the way
[jucl.ReentrantLock](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/ReentrantLock.html)
is used on JVM. On JVM it is a typealias to the later class, erased on JS.   

Condition variables (`notify`/`wait` and `signal`/`await`) are not supported.

### Testing lock-free data structures on JVM

You can optionally test lock-freedomness of lock-free data structures using
[`LockFreedomTestEnvironment`](atomicfu/src/jvmMain/kotlin/kotlinx/atomicfu/LockFreedomTestEnvironment.kt) class.
See example in [`LockFreeQueueLFTest`](atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/test/LockFreeQueueLFTest.kt).
Testing is performed by pausing one (random) thread before or after a random state-update operation and
making sure that all other threads can still make progress.

In order to make those test to actually perform lock-freedomness testing you need to configure an additional
execution of tests with the original (non-transformed) classes for Maven:

```xml

    
        
        
            maven-surefire-plugin
            
                
                    lockfree-test
                    test
                    
                        test
                    
                    
                        ${project.build.directory}/classes-pre-atomicfu
                        
                            **/*LFTest.*
                        
                    
                
            
        
    

```

For Gradle there is nothing else to add. Tests are always run using original (non-transformed) classes.

### Tracing operations

You can debug your tests tracing atomic operations with a special trace object:

```kotlin
private val trace = Trace()
private val current = atomic(0, trace)

fun update(x: Int): Int {           
    // custom trace message
    trace { "calling update($x)" }
    // automatic tracing of modification operations 
    return current.getAndAdd(x)
}
```      

All trace messages are stored in a cyclic array inside `trace`. 
 
You can optionally set the size of trace's message array and format function. For example, 
you can add a current thread name to the traced messages:

```kotlin
private val trace = Trace(size = 64) {   
    index, // index of a trace message 
    text   // text passed when invoking trace { text }
    -> "$index: [${Thread.currentThread().name}] $text" 
} 
```                           

`trace` is only seen before transformation and completely erased after on Kotlin/JVM and Kotlin/JS.