kotlinx.atomicfu alternatives and similar libraries
Based on the "Misc" category.
Alternatively, view kotlinx.atomicfu alternatives based on common mentions on social networks and blogs.
-
jclasslib
jclasslib bytecode viewer is a tool that visualizes all aspects of compiled Java class files and the contained bytecode. -
kotlin-logging
Lightweight logging framework for Kotlin. Used as a wrapper for slf4j with Kotlin extensions. -
kotlinx-datetime
A multiplatform Kotlin library for working with date and time. -
klock
Consistent and portable date and time utilities for multiplatform kotlin (JVM, JS and Common). -
kotlin-telegram-bot
A wrapper for the Telegram Bot API written in Kotlin. -
kotlinx.reflect.lite
Lightweight library allowing to introspect basic stuff about Kotlin symbols. -
Humanizer.jvm
Humanizer.jvm meets all your jvm needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities. -
actions-on-google-kotlin
Port of official Node.js SDK to Kotlin. Complete with all features and tests and nearly identical API. -
klutter
A mix of random small libraries for Kotlin, the smallest reside here until big enough for their own repository. -
solr-undertow
Solr Standalone Tiny and High performant server. -
kotlin-hashids
Library that generates short, unique, non-sequential hashes from numbers. -
SimpleDNN
SimpleDNN is a machine learning lightweight open-source library part of KotlinNLP and has been designed to support relevant neural network architectures in natural language processing tasks. -
kassava
This library provides some useful kotlin extension functions for implementing toString() and equals() without all of the boilerplate. -
kotlin-futures
A collections of extension functions to make the JVM Future, CompletableFuture, ListenableFuture API more functional and Kotlin like. -
units-of-measure
A type-safe dimensional analysis library for Kotlin. -
PrimeCalendar
Provides all of the java.util.Calendar functionalities for Civil, Persian, Hijri, Japanese, etc, as well as their conversion to each other. -
kasechange
Multiplatform Kotlin library to convert strings between various case formats including Camel Case, Snake Case, Pascal Case and Kebab Case -
kotlin-pluralizer
Kotlin extension to pluralize and singularize strings.
Get performance insights in less than 4 minutes
* Code Quality Rankings and insights are calculated and provided by Lumnify.
They vary from L1 to L5 with "L5" being the highest. Visit our partner's website for more details.
Do you think we are missing an alternative of kotlinx.atomicfu or a related project?
README
AtomicFU
The idiomatic way to use atomic operations in Kotlin.
- Code it like
AtomicReference/Int/Long
, but run it in production efficiently asAtomicXxxFieldUpdater
on Kotlin/JVM and as plain unboxed values on Kotlin/JS. - Use Kotlin-specific extensions (e.g. inline
updateAndGet
andgetAndUpdate
functions). - Compile-time dependency only (no runtime dependencies).
- Post-compilation bytecode transformer that declares all the relevant field updaters for you on Kotlin/JVM.
- Post-compilation JavaScript files transformer on Kotlin/JS.
- Multiplatform:
- Kotlin/Native is supported.
- However, Kotlin/Native works as library dependency at the moment (unlike Kotlin/JVM and Kotlin/JS).
- This enables writing common Kotlin code with atomics that compiles for JVM, JS, and Native.
- Gradle for all platforms and Maven for JVM are supported.
- Additional features include:
Example
Let us declare a top
variable for a lock-free stack implementation:
import kotlinx.atomicfu.* // import top-level functions from kotlinx.atomicfu
private val top = atomic<Node?>(null)
Use top.value
to perform volatile reads and writes:
fun isEmpty() = top.value == null // volatile read
fun clear() { top.value = null } // volatile write
Use compareAndSet
function directly:
if (top.compareAndSet(expect, update)) ...
Use higher-level looping primitives (inline extensions), for example:
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:
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:
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
orinternal 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, whileval tmp = top; tmp...
is not. - Do not leak references on atomic variables in other way (return, pass as params, etc).
- Do not read references on atomic variables into local variables,
e.g.
- Do not introduce complex data flow in parameters to atomic variable operations,
i.e.
top.value = complex_expression
andtop.compareAndSet(cur, complex_expression)
are not supported (more specifically,complex_expression
should not have branches in its compiled representation). Extractcomplex_expression
into a variable when needed. - Use the following convention if you need to expose the value of atomic property to the public:
private val _foo = atomic<T>(initial) // private atomic, convention is to name it with leading underscore
public var foo: T // public val/var
get() = _foo.value
set(value) { _foo.value = value }
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 if that needs tweaking.
buildscript {
ext.atomicfu_version = '0.14.3'
dependencies {
classpath "org.jetbrains.kotlinx:atomicfu-gradle-plugin:$atomicfu_version"
}
}
apply plugin: 'kotlinx-atomicfu'
JS
Configure add apply plugin just like for 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 for more details.
Apply the corresponding plugin just like for JVM.
Atomic references for Kotlin/Native are based on FreezableAtomicReference and every reference that is stored to the previously frozen (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:
dependencies {
compile "org.jetbrains.kotlinx:atomicfu-common:$atomicfu_version"
}
Additional configuration
There are the following additional parameters (with their defaults):
atomicfu {
dependenciesVersion = '0.14.3' // 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:
<properties>
<atomicfu.version>0.14.3</atomicfu.version>
</properties>
Declare provided dependency on the AtomicFU library (the users of the resulting artifact will not have a dependency on AtomicFU library):
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>atomicfu</artifactId>
<version>${atomicfu.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
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>
<plugins>
<!-- compile Kotlin files to staging directory -->
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<output>${project.build.directory}/classes-pre-atomicfu</output>
<!-- "VH" to use Java 9 VarHandle, "BOTH" to produce multi-version code -->
<variant>FU</variant>
</configuration>
</execution>
</executions>
</plugin>
<!-- transform classes with AtomicFU plugin -->
<plugin>
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>atomicfu-maven-plugin</artifactId>
<version>${atomicfu.version}</version>
<executions>
<execution>
<goals>
<goal>transform</goal>
</goals>
<configuration>
<input>${project.build.directory}/classes-pre-atomicfu</input>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
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
instead of AtomicXxxFieldUpdater
. Configure transformation variant
in Gradle build file:
atomicfu {
variant = "VH"
}
It can also create JEP 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 to support atomic operations.
val a = atomicArrayOfNulls<T>(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:
@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 writeclass MyClass : SynchronizedObject()
and then usesynchronized(instance) { ... }
extension function similarly to the synchronized function from the standard library that is available for JVM. TheSynchronizedObject
superclass gets erased (transformed toAny
) on JVM and JS, withsynchronized
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 writeval lock = reentrantLock()
to construct its instance and uselock
/tryLock
/unlock
functions orlock.withLock { ... }
extension function similarly to the way jucl.ReentrantLock 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:
<build>
<plugins>
<!-- additional test execution with surefire on non-transformed files -->
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>lockfree-test</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<classesDirectory>${project.build.directory}/classes-pre-atomicfu</classesDirectory>
<includes>
<include>**/*LFTest.*</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
For Gradle there is nothing else to add. Tests are always run using original (non-transformed) classes.
*Note that all licence references and agreements mentioned in the kotlinx.atomicfu README section above
are relevant to that project's source code only.