From c1a5a280f5352bf607b3d735e9d7b4604ed0aa17 Mon Sep 17 00:00:00 2001 From: mvicsokolova <82594708+mvicsokolova@users.noreply.github.com> Date: Tue, 25 Oct 2022 12:55:08 +0200 Subject: Readme update (#256) * README update * minor fixes --- README.md | 351 ++++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 207 insertions(+), 144 deletions(-) diff --git a/README.md b/README.md index c34cd44..251bb0e 100644 --- a/README.md +++ b/README.md @@ -9,26 +9,41 @@ >We do provide a compatibility of atomicfu-transformed artifacts between releases, but we do not provide >strict compatibility guarantees on plugin API and its general stability between Kotlin versions. -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 for JVM and JS/IR (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) - * [Tracing operations](#tracing-operations) - +**Atomicfu** is a multiplatform library that provides the idiomatic and effective way of using atomic operations in Kotlin. + +## Table of contents +- [Features](#features) +- [Example](#example) +- [Quickstart](#quickstart) + - [Apply plugin to a project](#apply-plugin) + - [Gradle configuration](#gradle-configuration) + - [Maven configuration](#maven-configuration) +- [Usage constraints](#usage-constraints) +- [Transformation modes](#transformation-modes) + - [Atomicfu compiler plugin](#atomicfu-compiler-plugin) +- [Options for post-compilation transformation](#options-for-post-compilation-transformation) + - [JVM options](#jvm-options) + - [JS options](#js-options) +- [More features](#more-features) + - [Arrays of atomic values](#arrays-of-atomic-values) + - [User-defined extensions on atomics](#user-defined-extensions-on-atomics) + - [Locks](#locks) + - [Tracing operations](#tracing-operations) +- [Kotlin/Native support](#kotlin-native-support) + + +## Features + +* Code it like a boxed value `atomic(0)`, but run it in production efficiently: + * as `java.util.concurrent.atomic.AtomicXxxFieldUpdater` on Kotlin/JVM + * as a plain unboxed value on Kotlin/JS +* Multiplatform: write common Kotlin code with atomics that compiles for Kotlin JVM, JS, and Native backends: + * Compile-only dependency for JVM and JS (no runtime dependencies) + * Compile and runtime dependency for Kotlin/Native +* Use Kotlin-specific extensions (e.g. inline `loop`, `update`, `updateAndGet` functions). +* Use atomic arrays, user-defined extensions on atomics and locks (see [more features](#more-features)). +* [Tracing operations](#tracing-operations) for debugging. + ## Example Let us declare a `top` variable for a lock-free stack implementation: @@ -78,14 +93,140 @@ 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 +## Quickstart +### Apply plugin +#### Gradle configuration + +Gradle configuration is supported for all platforms, minimal version is Gradle 6.8. + +In top-level build file: + +
+Kotlin + +```kotlin +buildscript { + repositories { + mavenCentral() + } + + dependencies { + classpath("org.jetbrains.kotlinx:atomicfu-gradle-plugin:0.18.4") + } +} + +apply(plugin = "kotlinx-atomicfu") +``` +
+ +
+Groovy + +```groovy +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath 'org.jetbrains.kotlinx:atomicfu-gradle-plugin:0.18.4' + } +} + +apply plugin: 'kotlinx-atomicfu' +``` +
+ +#### Maven configuration + +Maven configuration is supported for JVM projects. + + +
+Declare atomicfu version + +```xml + + 0.18.4 + +``` + +
+ +
+Declare provided dependency on the 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. + +
+Build steps + +```xml + + + + + org.jetbrains.kotlin + kotlin-maven-plugin + ${kotlin.version} + + + compile + compile + + compile + + + ${project.build.directory}/classes-pre-atomicfu + + + + + + + org.jetbrains.kotlinx + atomicfu-maven-plugin + ${atomicfu.version} + + + + transform + + + ${project.build.directory}/classes-pre-atomicfu + + FU + + + + + + +``` + +
+ +## Usage constraints * 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. + 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 @@ -96,72 +237,53 @@ operations. They can be also atomically modified via `+=` and `-=` operators. ```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 +## Transformation modes -Building with Gradle is supported for all platforms. +Basically, Atomicfu library provides an effective usage of atomic values by performing the transformations of the compiled code. +For JVM and JS there 2 transformation modes available: +* **Post-compilation transformation** that modifies the compiled bytecode or `*.js` files. +* **IR transformation** that is performed by the atomicfu compiler plugin. -### JVM +### Atomicfu compiler plugin -You will need Gradle 6.8 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. +Compiler plugin transformation is less fragile than transformation of the compiled sources +as it depends on the compiler IR tree. -```groovy -buildscript { - ext.atomicfu_version = '0.18.4' +To turn on IR transformation set these properties in your `gradle.properties` file: - dependencies { - classpath "org.jetbrains.kotlinx:atomicfu-gradle-plugin:$atomicfu_version" - } -} +
+For Kotlin >= 1.7.20 -apply plugin: 'kotlinx-atomicfu' +```groovy +kotlinx.atomicfu.enableJvmIrTransformation=true // for JVM IR transformation +kotlinx.atomicfu.enableJsIrTransformation=true // for JS IR transformation ``` -### JS - -Configure add apply plugin just like for [JVM](#jvm). +
-### Native +
-This library is available for Kotlin/Native (`atomicfu-native`). -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. + For Kotlin >= 1.6.20 and Kotlin < 1.7.20 -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`. +```groovy +kotlinx.atomicfu.enableIrTransformation=true // only JS IR transformation is supported +``` -### Common +
-If you write a common code that should get compiled or different platforms, add `org.jetbrains.kotlinx:atomicfu` -to your common code dependencies or apply `kotlinx-atomicfu` plugin that adds this dependency automatically: +Also for JS backend make sure that `ir` or `both` compiler mode is set: ```groovy -dependencies { - compile "org.jetbrains.kotlinx:atomicfu:$atomicfu_version" -} +kotlin.js.compiler=ir // or both ``` -## IR transformation for Kotlin/JS - -There is a new option to turn on IR transformation for Kotlin/JS backend. -You can add `kotlinx.atomicfu.enableIrTransformation=true` to your `gradle.properties` file in order to enable it. -Here is how transformation is performed for different [JS compiler modes](https://kotlinlang.org/docs/js-ir-compiler.html) with this option enabled: +## Options for post-compilation transformation -- `kotlin.js.compiler=legacy`: JavaScript transformer from the library is applied to the final compiled *.js files. -- `kotlin.js.compiler=ir`: compiler plugin transformations are appiled to the generated IR. -- `kotlin.js.compiler=both`: compiler plugin transformations are appiled to all compilations of IR targets, while compilations of legacy targets are transformed by the library. - -## Additional configuration +Some configuration options are available for _post-compilation transform tasks_ on JVM and JS. To set configuration options you should create `atomicfu` section in a `build.gradle` file, like this: @@ -171,7 +293,7 @@ atomicfu { } ``` -### JVM transformation options +### JVM options To turn off transformation for Kotlin/JVM set option `transformJvm` to `false`. @@ -182,7 +304,7 @@ Here are the valid options: this option is supported for JDK 9+. - `BOTH` – [multi-release jar file](https://openjdk.java.net/jeps/238) will be created with both `AtomicXxxFieldUpdater` for JDK <= 8 and `VarHandle` for JDK 9+. -### JS transformation options +### JS options To turn off transformation for Kotlin/JS set option `transformJs` to `false`. @@ -191,85 +313,14 @@ Here are all available configuration options (with their defaults): atomicfu { dependenciesVersion = '0.18.4' // set to null to turn-off auto dependencies transformJvm = true // set to false to turn off JVM transformation - jvmVariant = "FU" // JVM transformation variant: FU,VH, or BOTH - jsVariant = "JS" // JS transformation variant: JS or IR - verbose = false // set to true to be more verbose + jvmVariant = "FU" // JVM transformation variant: FU,VH, or BOTH + transformJs = true // set to false to turn off JVM transformation } ``` -## Maven build setup - -Declare AtomicFU version: - -```xml - - 0.18.4 - -``` - -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 - - - - - - - org.jetbrains.kotlinx - atomicfu-maven-plugin - ${atomicfu.version} - - - - transform - - - ${project.build.directory}/classes-pre-atomicfu - - FU - - - - - - -``` +## More features -## Additional features - -AtomicFU provides some additional features that you can optionally use. +AtomicFU provides some additional features that you can use. ### Arrays of atomic values @@ -350,3 +401,15 @@ private val trace = Trace(size = 64) { `trace` is only seen before transformation and completely erased after on Kotlin/JVM and Kotlin/JS. +## Kotlin Native support + +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`. + -- cgit v1.2.3