[atomicfu-JVM] Preparation for commonization of JVM and K/N transformers

The following updates in the JVM/IR plugin were made:
* Lots of refactoring with preparation for K/N support: commonization of transformations.
* Improved error handling (checks for visibility constraints, appending message about usage constraints in case of an error).
* Explicit requirements for the visibility of atomic properties: to prevent leaking they should be private/internal or be members of private/internal classes.
* Fixed visibility of generated properties: volatile properties are always private and atomic updaters have the same visibility as the original atomic property.
* Volatile fields are generated from scratch and original atomic properties are removed.
* Delegated properties support is fixed (only declaration in the same scope is allowed).
* Non-inline atomic extensions are forbidden.
* For top-level atomics: only one wrapper class per file (with corresponding visibility) is generated.
* Bug fixes.

The corresponding tickets: 
https://github.com/Kotlin/kotlinx-atomicfu/issues/322
KT-60528



Merge-request: KT-MR-10579
Merged-by: Maria Sokolova <maria.sokolova@jetbrains.com>
This commit is contained in:
mvicsokolova
2023-07-20 13:59:23 +00:00
committed by Space Team
parent 6ca95dc338
commit 5c5367d377
92 changed files with 3480 additions and 2575 deletions
@@ -0,0 +1,79 @@
import kotlinx.atomicfu.*
import kotlin.test.*
class ArrayInlineExtensionTest {
private val intArr = AtomicIntArray(10)
private val a = atomic(100)
private val longArr = AtomicLongArray(10)
private val refArr = atomicArrayOfNulls<Any?>(5)
class A(val s: String)
private inline fun casLoop(to: Int): Int {
intArr[0].loop { cur ->
if (intArr[0].compareAndSet(cur, to)) return intArr[0].value
return 777
}
}
private inline fun casLoopExpression(to: Long): Long = longArr[3].loop { cur ->
if (longArr[3].compareAndSet(cur, to)) return longArr[3].value
return 777
}
private inline fun AtomicInt.extensionLoop(to: Int): Int {
loop { cur ->
if (compareAndSet(cur, to)) return value
return 777
}
}
private inline fun AtomicInt.extensionLoopExpression(to: Int): Int = loop { cur ->
lazySet(cur + 10)
return if (compareAndSet(cur, to)) value else incrementAndGet()
}
private inline fun AtomicInt.extensionLoopMixedReceivers(first: Int, second: Int, index: Int): Int {
loop { cur ->
compareAndSet(cur, first)
intArr[index].compareAndSet(first, second)
return value
}
}
private inline fun AtomicInt.extensionLoopRecursive(to: Int): Int {
loop { cur ->
compareAndSet(cur, to)
a.extensionLoop(5)
return value
}
}
private inline fun AtomicInt.foo(to: Int): Int {
loop { cur ->
if (compareAndSet(cur, to)) return 777
else return value
}
}
private inline fun AtomicInt.bar(delta: Int): Int {
return foo(value + delta)
}
fun testIntExtensionLoops() {
assertEquals(5, casLoop(5))
assertEquals(6, casLoopExpression(6))
assertEquals(66, intArr[1].extensionLoop(66))
assertEquals(66, intArr[2].extensionLoop(66))
assertEquals(77, intArr[1].extensionLoopExpression(777))
assertEquals(99, intArr[1].extensionLoopMixedReceivers(88, 99, 1))
assertEquals(100, intArr[1].extensionLoopRecursive(100))
assertEquals(777, intArr[1].bar(100))
}
}
fun box(): String {
val testClass = ArrayInlineExtensionTest()
testClass.testIntExtensionLoops()
return "OK"
}
@@ -0,0 +1,51 @@
@kotlin.Metadata
public final class ArrayInlineExtensionTest$A {
// source: 'ArrayInlineExtensionTest.kt'
private final @org.jetbrains.annotations.NotNull field s: java.lang.String
public method <init>(@org.jetbrains.annotations.NotNull p0: java.lang.String): void
public final @org.jetbrains.annotations.NotNull method getS(): java.lang.String
public final inner class ArrayInlineExtensionTest$A
}
@kotlin.Metadata
public final class ArrayInlineExtensionTest {
// source: 'ArrayInlineExtensionTest.kt'
private synthetic final static field a$volatile$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private synthetic volatile field a$volatile: int
private synthetic final field intArr: java.util.concurrent.atomic.AtomicIntegerArray
private synthetic final field longArr: java.util.concurrent.atomic.AtomicLongArray
private synthetic final field refArr: java.util.concurrent.atomic.AtomicReferenceArray
static method <clinit>(): void
public method <init>(): void
private synthetic final method bar$atomicfu$array(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int, p3: int): int
private synthetic final method bar$atomicfu(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p2: int): int
private final method casLoop(p0: int): int
private final method casLoopExpression(p0: long): long
private synthetic final method extensionLoop$atomicfu$array(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int, p3: int): int
private synthetic final method extensionLoop$atomicfu(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p2: int): int
private synthetic final method extensionLoopExpression$atomicfu$array(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int, p3: int): int
private synthetic final method extensionLoopExpression$atomicfu(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p2: int): int
private synthetic final method extensionLoopMixedReceivers$atomicfu$array(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int, p3: int, p4: int, p5: int): int
private synthetic final method extensionLoopMixedReceivers$atomicfu(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p2: int, p3: int, p4: int): int
private synthetic final method extensionLoopRecursive$atomicfu$array(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int, p3: int): int
private synthetic final method extensionLoopRecursive$atomicfu(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p2: int): int
private synthetic final method foo$atomicfu$array(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int, p3: int): int
private synthetic final method foo$atomicfu(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p2: int): int
private synthetic final static method getA$volatile$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private synthetic final method getA$volatile(): int
private synthetic final method getIntArr(): java.util.concurrent.atomic.AtomicIntegerArray
private synthetic final method getLongArr(): java.util.concurrent.atomic.AtomicLongArray
private synthetic final method getRefArr(): java.util.concurrent.atomic.AtomicReferenceArray
private synthetic final method loop$atomicfu$array(p0: java.util.concurrent.atomic.AtomicIntegerArray, p1: int, p2: kotlin.jvm.functions.Function1): void
private synthetic final method loop$atomicfu$array(p0: java.util.concurrent.atomic.AtomicLongArray, p1: int, p2: kotlin.jvm.functions.Function1): void
private synthetic final method loop$atomicfu(p0: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p1: kotlin.jvm.functions.Function1, p2: java.lang.Object): void
private synthetic final method setA$volatile(p0: int): void
public final method testIntExtensionLoops(): void
public final inner class ArrayInlineExtensionTest$A
}
@kotlin.Metadata
public final class ArrayInlineExtensionTestKt {
// source: 'ArrayInlineExtensionTest.kt'
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
}
@@ -0,0 +1,44 @@
import kotlinx.atomicfu.*
import kotlin.test.*
class ArrayInlineFunctionTest {
private val anyArr = atomicArrayOfNulls<Any?>(5)
private val refArr = atomicArrayOfNulls<Box>(5)
private data class Box(val n: Int)
fun testSetArrayElementValueInLoop() {
anyArr[0].loop { cur ->
assertTrue(anyArr[0].compareAndSet(cur, IntArray(5)))
return
}
}
private fun action(cur: Box?) = cur?.let { Box(cur.n * 10) }
fun testArrayElementUpdate() {
refArr[0].lazySet(Box(5))
refArr[0].update { cur -> cur?.let { Box(cur.n * 10) } }
assertEquals(refArr[0].value!!.n, 50)
}
fun testArrayElementGetAndUpdate() {
refArr[0].lazySet(Box(5))
assertEquals(refArr[0].getAndUpdate { cur -> action(cur) }!!.n, 5)
assertEquals(refArr[0].value!!.n, 50)
}
fun testArrayElementUpdateAndGet() {
refArr[0].lazySet(Box(5))
assertEquals(refArr[0].updateAndGet { cur -> action(cur) }!!.n, 50)
}
}
fun box(): String {
val testClass = ArrayInlineFunctionTest()
testClass.testSetArrayElementValueInLoop()
testClass.testArrayElementGetAndUpdate()
testClass.testArrayElementUpdate()
testClass.testArrayElementUpdateAndGet()
return "OK"
}
@@ -0,0 +1,40 @@
@kotlin.Metadata
final class ArrayInlineFunctionTest$Box {
// source: 'ArrayLoopTest.kt'
private final field n: int
public method <init>(p0: int): void
public final method component1(): int
public synthetic static method copy$default(p0: ArrayInlineFunctionTest$Box, p1: int, p2: int, p3: java.lang.Object): ArrayInlineFunctionTest$Box
public final @org.jetbrains.annotations.NotNull method copy(p0: int): ArrayInlineFunctionTest$Box
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
public final method getN(): int
public method hashCode(): int
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
private final inner class ArrayInlineFunctionTest$Box
}
@kotlin.Metadata
public final class ArrayInlineFunctionTest {
// source: 'ArrayLoopTest.kt'
private synthetic final field anyArr: java.util.concurrent.atomic.AtomicReferenceArray
private synthetic final field refArr: java.util.concurrent.atomic.AtomicReferenceArray
public method <init>(): void
private final method action(p0: ArrayInlineFunctionTest$Box): ArrayInlineFunctionTest$Box
private synthetic final method getAndUpdate$atomicfu$array(p0: java.util.concurrent.atomic.AtomicReferenceArray, p1: int, p2: kotlin.jvm.functions.Function1): java.lang.Object
private synthetic final method getAnyArr(): java.util.concurrent.atomic.AtomicReferenceArray
private synthetic final method getRefArr(): java.util.concurrent.atomic.AtomicReferenceArray
private synthetic final method loop$atomicfu$array(p0: java.util.concurrent.atomic.AtomicReferenceArray, p1: int, p2: kotlin.jvm.functions.Function1): void
public final method testArrayElementGetAndUpdate(): void
public final method testArrayElementUpdate(): void
public final method testArrayElementUpdateAndGet(): void
public final method testSetArrayElementValueInLoop(): void
private synthetic final method update$atomicfu$array(p0: java.util.concurrent.atomic.AtomicReferenceArray, p1: int, p2: kotlin.jvm.functions.Function1): void
private synthetic final method updateAndGet$atomicfu$array(p0: java.util.concurrent.atomic.AtomicReferenceArray, p1: int, p2: kotlin.jvm.functions.Function1): java.lang.Object
private final inner class ArrayInlineFunctionTest$Box
}
@kotlin.Metadata
public final class ArrayLoopTestKt {
// source: 'ArrayLoopTest.kt'
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
}
@@ -0,0 +1,51 @@
import kotlinx.atomicfu.*
import kotlin.test.*
class LoopTest {
private val a = atomic(10)
private val b = atomic(11)
private val c = atomic(12)
private val r = atomic<String>("aaa")
private val intArr = AtomicIntArray(10)
private inline fun AtomicInt.extensionEmbeddedLoops(to: Int): Int =
loop { cur1 ->
compareAndSet(cur1, to)
loop { cur2 ->
return cur2
}
}
private inline fun embeddedLoops(to: Int): Int =
a.loop { aValue ->
b.loop { bValue ->
if (b.compareAndSet(bValue, to)) return aValue + bValue
}
}
private inline fun embeddedUpdate(to: Int): Int =
a.loop { aValue ->
a.compareAndSet(aValue, to)
return a.updateAndGet { cur -> cur + 100 }
}
private inline fun AtomicRef<String>.extesntionEmbeddedRefUpdate(to: String): String =
loop { value ->
compareAndSet(value, to)
return updateAndGet { cur -> "${cur}AAA" }
}
fun test() {
assertEquals(21, embeddedLoops(12))
assertEquals(77, c.extensionEmbeddedLoops(77))
assertEquals(66, intArr[0].extensionEmbeddedLoops(66))
assertEquals(166, embeddedUpdate(66))
assertEquals("bbbAAA", r.extesntionEmbeddedRefUpdate("bbb"))
}
}
fun box(): String {
val testClass = LoopTest()
testClass.test()
return "OK"
}
@@ -0,0 +1,48 @@
@kotlin.Metadata
public final class ComplexLoopTestKt {
// source: 'ComplexLoopTest.kt'
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
}
@kotlin.Metadata
public final class LoopTest {
// source: 'ComplexLoopTest.kt'
private synthetic final static field a$volatile$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private synthetic volatile field a$volatile: int
private synthetic final static field b$volatile$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private synthetic volatile field b$volatile: int
private synthetic final static field c$volatile$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private synthetic volatile field c$volatile: int
private synthetic final field intArr: java.util.concurrent.atomic.AtomicIntegerArray
private synthetic final static field r$volatile$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
private synthetic volatile field r$volatile: java.lang.Object
static method <clinit>(): void
public method <init>(): void
private final method embeddedLoops(p0: int): int
private final method embeddedUpdate(p0: int): int
private synthetic final method extensionEmbeddedLoops$atomicfu$array(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int, p3: int): int
private synthetic final method extensionEmbeddedLoops$atomicfu(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p2: int): int
private synthetic final method extesntionEmbeddedRefUpdate$atomicfu$array(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicReferenceArray, p2: int, p3: java.lang.String): java.lang.String
private synthetic final method extesntionEmbeddedRefUpdate$atomicfu(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicReferenceFieldUpdater, p2: java.lang.String): java.lang.String
private synthetic final static method getA$volatile$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private synthetic final method getA$volatile(): int
private synthetic final static method getB$volatile$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private synthetic final method getB$volatile(): int
private synthetic final static method getC$volatile$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private synthetic final method getC$volatile(): int
private synthetic final method getIntArr(): java.util.concurrent.atomic.AtomicIntegerArray
private synthetic final static method getR$volatile$FU(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
private synthetic final method getR$volatile(): java.lang.Object
private synthetic final method loop$atomicfu$array(p0: java.util.concurrent.atomic.AtomicIntegerArray, p1: int, p2: kotlin.jvm.functions.Function1): void
private synthetic final method loop$atomicfu$array(p0: java.util.concurrent.atomic.AtomicReferenceArray, p1: int, p2: kotlin.jvm.functions.Function1): void
private synthetic final method loop$atomicfu(p0: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p1: kotlin.jvm.functions.Function1, p2: java.lang.Object): void
private synthetic final method loop$atomicfu(p0: java.util.concurrent.atomic.AtomicReferenceFieldUpdater, p1: kotlin.jvm.functions.Function1, p2: java.lang.Object): void
private synthetic final method setA$volatile(p0: int): void
private synthetic final method setB$volatile(p0: int): void
private synthetic final method setC$volatile(p0: int): void
private synthetic final method setR$volatile(p0: java.lang.Object): void
public final method test(): void
private synthetic final method updateAndGet$atomicfu$array(p0: java.util.concurrent.atomic.AtomicReferenceArray, p1: int, p2: kotlin.jvm.functions.Function1): java.lang.Object
private synthetic final method updateAndGet$atomicfu(p0: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p1: kotlin.jvm.functions.Function1, p2: java.lang.Object): int
private synthetic final method updateAndGet$atomicfu(p0: java.util.concurrent.atomic.AtomicReferenceFieldUpdater, p1: kotlin.jvm.functions.Function1, p2: java.lang.Object): java.lang.Object
}
@@ -0,0 +1,92 @@
import kotlinx.atomicfu.*
import kotlin.test.*
class LoopTest {
private val a = atomic(0)
private val a1 = atomic(1)
private val b = atomic(true)
private val l = atomic(5000000000)
private val r = atomic<A>(A("aaaa"))
private val rs = atomic<String>("bbbb")
class A(val s: String)
private inline fun casLoop(to: Int): Int {
a.loop { cur ->
if (a.compareAndSet(cur, to)) return a.value
return 777
}
}
private inline fun casLoopExpression(to: Int): Int = a.loop { cur ->
if (a.compareAndSet(cur, to)) return a.value
return 777
}
private inline fun AtomicInt.extensionLoop(to: Int): Int {
loop { cur ->
if (compareAndSet(cur, to)) return value
return 777
}
}
private inline fun AtomicInt.extensionLoopExpression(to: Int): Int = loop { cur ->
lazySet(cur + 10)
return if (compareAndSet(cur, to)) value else incrementAndGet()
}
private inline fun AtomicInt.extensionLoopMixedReceivers(first: Int, second: Int): Int {
loop { cur ->
compareAndSet(cur, first)
a.compareAndSet(first, second)
return value
}
}
private inline fun AtomicInt.extensionLoopRecursive(to: Int): Int {
loop { cur ->
compareAndSet(cur, to)
a.extensionLoop(5)
return value
}
}
private inline fun AtomicInt.foo(to: Int): Int {
loop { cur ->
if (compareAndSet(cur, to)) return 777
else return value
}
}
private inline fun AtomicInt.bar(delta: Int): Int {
return foo(value + delta)
}
fun testIntExtensionLoops() {
assertEquals(5, casLoop(5))
assertEquals(6, casLoopExpression(6))
assertEquals(66, a.extensionLoop(66))
assertEquals(77, a.extensionLoopExpression(777))
assertEquals(99, a.extensionLoopMixedReceivers(88, 99))
assertEquals(5, a.extensionLoopRecursive(100))
assertEquals(777, a.bar(100))
}
}
private val ref = atomic<String>("aaa")
private inline fun AtomicRef<String>.topLevelExtensionLoop(to: String): String = loop { cur ->
lazySet(cur + to)
return value
}
fun testTopLevelExtensionLoop() {
assertEquals("aaattt", ref.topLevelExtensionLoop("ttt"))
}
fun box(): String {
val testClass = LoopTest()
testClass.testIntExtensionLoops()
testTopLevelExtensionLoop()
return "OK"
}
@@ -0,0 +1,91 @@
@kotlin.Metadata
synthetic final class ExtensionLoopTest$VolatileWrapper$atomicfu$private {
// source: 'ExtensionLoopTest.kt'
private synthetic final static field ref$volatile$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
private synthetic volatile field ref$volatile: java.lang.Object
static method <clinit>(): void
private method <init>(): void
public synthetic method <init>(p0: kotlin.jvm.internal.DefaultConstructorMarker): void
public synthetic final static method access$getRef$volatile$FU(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
private synthetic final static method getRef$volatile$FU(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
private synthetic final method getRef$volatile(): java.lang.Object
private synthetic final method setRef$volatile(p0: java.lang.Object): void
}
@kotlin.Metadata
public final class ExtensionLoopTestKt {
// source: 'ExtensionLoopTest.kt'
private synthetic final static field extensionLoopTest$VolatileWrapper$atomicfu$private: ExtensionLoopTest$VolatileWrapper$atomicfu$private
static method <clinit>(): void
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
private synthetic final static method getExtensionLoopTest$VolatileWrapper$atomicfu$private(): ExtensionLoopTest$VolatileWrapper$atomicfu$private
private synthetic final static method loop$atomicfu$array(p0: java.util.concurrent.atomic.AtomicReferenceArray, p1: int, p2: kotlin.jvm.functions.Function1): void
private synthetic final static method loop$atomicfu(p0: java.util.concurrent.atomic.AtomicReferenceFieldUpdater, p1: kotlin.jvm.functions.Function1, p2: java.lang.Object): void
public final static method testTopLevelExtensionLoop(): void
private synthetic final static method topLevelExtensionLoop$atomicfu$array(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicReferenceArray, p2: int, p3: java.lang.String): java.lang.String
private synthetic final static method topLevelExtensionLoop$atomicfu(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicReferenceFieldUpdater, p2: java.lang.String): java.lang.String
}
@kotlin.Metadata
public final class LoopTest$A {
// source: 'ExtensionLoopTest.kt'
private final @org.jetbrains.annotations.NotNull field s: java.lang.String
public method <init>(@org.jetbrains.annotations.NotNull p0: java.lang.String): void
public final @org.jetbrains.annotations.NotNull method getS(): java.lang.String
public final inner class LoopTest$A
}
@kotlin.Metadata
public final class LoopTest {
// source: 'ExtensionLoopTest.kt'
private synthetic final static field a$volatile$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private synthetic volatile field a$volatile: int
private synthetic final static field a1$volatile$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private synthetic volatile field a1$volatile: int
private synthetic final static field b$volatile$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private synthetic volatile field b$volatile: int
private synthetic final static field l$volatile$FU: java.util.concurrent.atomic.AtomicLongFieldUpdater
private synthetic volatile field l$volatile: long
private synthetic final static field r$volatile$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
private synthetic volatile field r$volatile: java.lang.Object
private synthetic final static field rs$volatile$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
private synthetic volatile field rs$volatile: java.lang.Object
static method <clinit>(): void
public method <init>(): void
private synthetic final method bar$atomicfu$array(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int, p3: int): int
private synthetic final method bar$atomicfu(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p2: int): int
private final method casLoop(p0: int): int
private final method casLoopExpression(p0: int): int
private synthetic final method extensionLoop$atomicfu$array(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int, p3: int): int
private synthetic final method extensionLoop$atomicfu(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p2: int): int
private synthetic final method extensionLoopExpression$atomicfu$array(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int, p3: int): int
private synthetic final method extensionLoopExpression$atomicfu(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p2: int): int
private synthetic final method extensionLoopMixedReceivers$atomicfu$array(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int, p3: int, p4: int): int
private synthetic final method extensionLoopMixedReceivers$atomicfu(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p2: int, p3: int): int
private synthetic final method extensionLoopRecursive$atomicfu$array(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int, p3: int): int
private synthetic final method extensionLoopRecursive$atomicfu(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p2: int): int
private synthetic final method foo$atomicfu$array(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int, p3: int): int
private synthetic final method foo$atomicfu(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p2: int): int
private synthetic final static method getA$volatile$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private synthetic final method getA$volatile(): int
private synthetic final static method getA1$volatile$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private synthetic final method getA1$volatile(): int
private synthetic final static method getB$volatile$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private synthetic final method getB$volatile(): int
private synthetic final static method getL$volatile$FU(): java.util.concurrent.atomic.AtomicLongFieldUpdater
private synthetic final method getL$volatile(): long
private synthetic final static method getR$volatile$FU(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
private synthetic final method getR$volatile(): java.lang.Object
private synthetic final static method getRs$volatile$FU(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
private synthetic final method getRs$volatile(): java.lang.Object
private synthetic final method loop$atomicfu$array(p0: java.util.concurrent.atomic.AtomicIntegerArray, p1: int, p2: kotlin.jvm.functions.Function1): void
private synthetic final method loop$atomicfu(p0: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p1: kotlin.jvm.functions.Function1, p2: java.lang.Object): void
private synthetic final method setA$volatile(p0: int): void
private synthetic final method setA1$volatile(p0: int): void
private synthetic final method setB$volatile(p0: int): void
private synthetic final method setL$volatile(p0: long): void
private synthetic final method setR$volatile(p0: java.lang.Object): void
private synthetic final method setRs$volatile(p0: java.lang.Object): void
public final method testIntExtensionLoops(): void
public final inner class LoopTest$A
}
@@ -0,0 +1,115 @@
import kotlinx.atomicfu.*
import kotlin.test.*
class ExtensionsTest {
private val a = atomic(0)
private val l = atomic(0L)
private val s = atomic<String?>(null)
private val b = atomic(true)
fun testScopedFieldGetters() {
check(a.value == 0)
val update = 3
a.lazySet(update)
check(a.compareAndSet(update, 8))
a.lazySet(1)
check(a.value == 1)
check(a.getAndSet(2) == 1)
check(a.value == 2)
check(a.getAndIncrement() == 2)
check(a.value == 3)
check(a.getAndDecrement() == 3)
check(a.value == 2)
check(a.getAndAdd(2) == 2)
check(a.value == 4)
check(a.addAndGet(3) == 7)
check(a.value == 7)
check(a.incrementAndGet() == 8)
check(a.value == 8)
check(a.decrementAndGet() == 7)
check(a.value == 7)
check(a.compareAndSet(7, 10))
}
private inline fun AtomicInt.intExtensionArithmetic() {
value = 0
check(value == 0)
val update = 3
lazySet(update)
check(compareAndSet(update, 8))
lazySet(1)
check(value == 1)
check(getAndSet(2) == 1)
check(value == 2)
check(getAndIncrement() == 2)
check(value == 3)
check(getAndDecrement() == 3)
check(value == 2)
check(getAndAdd(2) == 2)
check(value == 4)
check(addAndGet(3) == 7)
check(value == 7)
check(incrementAndGet() == 8)
check(value == 8)
check(decrementAndGet() == 7)
check(value == 7)
check(compareAndSet(7, 10))
check(compareAndSet(value, 55))
check(value == 55)
}
private inline fun AtomicLong.longExtensionArithmetic() {
value = 2424920024888888848
check(value == 2424920024888888848)
lazySet(8424920024888888848)
check(value == 8424920024888888848)
check(getAndSet(8924920024888888848) == 8424920024888888848)
check(value == 8924920024888888848)
check(incrementAndGet() == 8924920024888888849) // fails
check(value == 8924920024888888849)
check(getAndDecrement() == 8924920024888888849)
check(value == 8924920024888888848)
check(getAndAdd(100000000000000000) == 8924920024888888848)
check(value == 9024920024888888848)
check(addAndGet(-9223372036854775807) == -198452011965886959)
check(value == -198452011965886959)
check(incrementAndGet() == -198452011965886958)
check(value == -198452011965886958)
check(decrementAndGet() == -198452011965886959)
check(value == -198452011965886959)
}
private inline fun AtomicRef<String?>.refExtension() {
value = "aaa"
check(value == "aaa")
lazySet("bb")
check(value == "bb")
check(getAndSet("ccc") == "bb")
check(value == "ccc")
}
private inline fun AtomicBoolean.booleanExtensionArithmetic() {
value = false
check(!value)
lazySet(true)
check(value)
check(getAndSet(true))
check(compareAndSet(value, false))
check(!value)
}
fun testExtension() {
a.intExtensionArithmetic()
l.longExtensionArithmetic()
s.refExtension()
b.booleanExtensionArithmetic()
}
}
fun box(): String {
val testClass = ExtensionsTest()
testClass.testScopedFieldGetters()
testClass.testExtension()
return "OK"
}
@@ -0,0 +1,42 @@
@kotlin.Metadata
public final class ExtensionsTest {
// source: 'ExtensionsTest.kt'
private synthetic final static field a$volatile$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private synthetic volatile field a$volatile: int
private synthetic final static field b$volatile$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private synthetic volatile field b$volatile: int
private synthetic final static field l$volatile$FU: java.util.concurrent.atomic.AtomicLongFieldUpdater
private synthetic volatile field l$volatile: long
private synthetic final static field s$volatile$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
private synthetic volatile field s$volatile: java.lang.Object
static method <clinit>(): void
public method <init>(): void
private synthetic final method booleanExtensionArithmetic$atomicfu$array(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int): void
private synthetic final method booleanExtensionArithmetic$atomicfu(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater): void
private synthetic final static method getA$volatile$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private synthetic final method getA$volatile(): int
private synthetic final static method getB$volatile$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private synthetic final method getB$volatile(): int
private synthetic final static method getL$volatile$FU(): java.util.concurrent.atomic.AtomicLongFieldUpdater
private synthetic final method getL$volatile(): long
private synthetic final static method getS$volatile$FU(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
private synthetic final method getS$volatile(): java.lang.Object
private synthetic final method intExtensionArithmetic$atomicfu$array(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int): void
private synthetic final method intExtensionArithmetic$atomicfu(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater): void
private synthetic final method longExtensionArithmetic$atomicfu$array(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicLongArray, p2: int): void
private synthetic final method longExtensionArithmetic$atomicfu(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicLongFieldUpdater): void
private synthetic final method refExtension$atomicfu$array(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicReferenceArray, p2: int): void
private synthetic final method refExtension$atomicfu(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicReferenceFieldUpdater): void
private synthetic final method setA$volatile(p0: int): void
private synthetic final method setB$volatile(p0: int): void
private synthetic final method setL$volatile(p0: long): void
private synthetic final method setS$volatile(p0: java.lang.Object): void
public final method testExtension(): void
public final method testScopedFieldGetters(): void
}
@kotlin.Metadata
public final class ExtensionsTestKt {
// source: 'ExtensionsTest.kt'
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
}
@@ -0,0 +1,33 @@
import kotlinx.atomicfu.*
import kotlin.test.*
class InlineExtensionWithTypeParameterTest {
abstract class Segment<S : Segment<S>>(val id: Int)
class SemaphoreSegment(id: Int) : Segment<SemaphoreSegment>(id)
private inline fun <S : Segment<S>> AtomicRef<S>.foo(
id: Int,
startFrom: S
): Int {
lazySet(startFrom)
return value.getSegmentId()
}
private inline fun <S : Segment<S>> S.getSegmentId(): Int {
var cur: S = this
return cur.id
}
private val sref = atomic(SemaphoreSegment(0))
fun testInlineExtensionWithTypeParameter() {
val s = SemaphoreSegment(77)
assertEquals(77, sref.foo(0, s))
}
}
fun box(): String {
val testClass = InlineExtensionWithTypeParameterTest()
testClass.testInlineExtensionWithTypeParameter()
return "OK"
}
@@ -0,0 +1,40 @@
@kotlin.Metadata
public abstract class InlineExtensionWithTypeParameterTest$Segment {
// source: 'InlineExtensionWithTypeParameterTest.kt'
private final field id: int
public method <init>(p0: int): void
public final method getId(): int
public abstract inner class InlineExtensionWithTypeParameterTest$Segment
}
@kotlin.Metadata
public final class InlineExtensionWithTypeParameterTest$SemaphoreSegment {
// source: 'InlineExtensionWithTypeParameterTest.kt'
public method <init>(p0: int): void
public abstract inner class InlineExtensionWithTypeParameterTest$Segment
public final inner class InlineExtensionWithTypeParameterTest$SemaphoreSegment
}
@kotlin.Metadata
public final class InlineExtensionWithTypeParameterTest {
// source: 'InlineExtensionWithTypeParameterTest.kt'
private synthetic final static field sref$volatile$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
private synthetic volatile field sref$volatile: java.lang.Object
static method <clinit>(): void
public method <init>(): void
private synthetic final method foo$atomicfu$array(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicReferenceArray, p2: int, p3: int, p4: InlineExtensionWithTypeParameterTest$Segment): int
private synthetic final method foo$atomicfu(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicReferenceFieldUpdater, p2: int, p3: InlineExtensionWithTypeParameterTest$Segment): int
private final method getSegmentId(p0: InlineExtensionWithTypeParameterTest$Segment): int
private synthetic final static method getSref$volatile$FU(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
private synthetic final method getSref$volatile(): java.lang.Object
private synthetic final method setSref$volatile(p0: java.lang.Object): void
public final method testInlineExtensionWithTypeParameter(): void
public abstract inner class InlineExtensionWithTypeParameterTest$Segment
public final inner class InlineExtensionWithTypeParameterTest$SemaphoreSegment
}
@kotlin.Metadata
public final class InlineExtensionWithTypeParameterTestKt {
// source: 'InlineExtensionWithTypeParameterTest.kt'
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
}
@@ -0,0 +1,52 @@
import kotlinx.atomicfu.*
import kotlin.test.*
class LambdaTest {
private val a = atomic(0)
private val rs = atomic<String>("bbbb")
private inline fun <T> inlineLambda(
arg: T,
crossinline block: (T) -> Unit
) = block(arg)
fun loopInLambda1(to: Int) = inlineLambda(to) sc@ { arg ->
a.loop { value ->
a.compareAndSet(value, arg)
return@sc
}
}
fun loopInLambda2(to: Int) = inlineLambda(to) { arg1 ->
inlineLambda(arg1) sc@ { arg2 ->
a.loop { value ->
a.compareAndSet(value, arg2)
return@sc
}
}
}
fun loopInLambda2Ref(to: String) = inlineLambda(to) { arg1 ->
inlineLambda(arg1) sc@ { arg2 ->
rs.loop { value ->
rs.compareAndSet(value, arg2)
return@sc
}
}
}
fun test() {
loopInLambda1(34)
assertEquals(34, a.value)
loopInLambda1(77)
assertEquals(77, a.value)
loopInLambda2Ref("bbb")
assertEquals("bbb", rs.value)
}
}
fun box(): String {
val testClass = LambdaTest()
testClass.test()
return "OK"
}
@@ -0,0 +1,31 @@
@kotlin.Metadata
public final class LambdaTest {
// source: 'LambdaTest.kt'
private synthetic final static field a$volatile$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private synthetic volatile field a$volatile: int
private synthetic final static field rs$volatile$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
private synthetic volatile field rs$volatile: java.lang.Object
static method <clinit>(): void
public method <init>(): void
public synthetic final static method access$getA$volatile$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
public synthetic final static method access$getRs$volatile$FU(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
private synthetic final static method getA$volatile$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private synthetic final method getA$volatile(): int
private synthetic final static method getRs$volatile$FU(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
private synthetic final method getRs$volatile(): java.lang.Object
private final method inlineLambda(p0: java.lang.Object, p1: kotlin.jvm.functions.Function1): void
private synthetic final method loop$atomicfu(p0: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p1: kotlin.jvm.functions.Function1, p2: java.lang.Object): void
private synthetic final method loop$atomicfu(p0: java.util.concurrent.atomic.AtomicReferenceFieldUpdater, p1: kotlin.jvm.functions.Function1, p2: java.lang.Object): void
public final method loopInLambda1(p0: int): void
public final method loopInLambda2(p0: int): void
public final method loopInLambda2Ref(@org.jetbrains.annotations.NotNull p0: java.lang.String): void
private synthetic final method setA$volatile(p0: int): void
private synthetic final method setRs$volatile(p0: java.lang.Object): void
public final method test(): void
}
@kotlin.Metadata
public final class LambdaTestKt {
// source: 'LambdaTest.kt'
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
}
@@ -0,0 +1,57 @@
import kotlinx.atomicfu.*
import kotlin.test.*
class LockFreeIntBitsTest {
fun testBasic() {
val bs = LockFreeIntBits()
assertTrue(!bs[0])
assertTrue(bs.bitSet(0))
assertTrue(bs[0])
assertTrue(!bs.bitSet(0))
assertTrue(!bs[1])
assertTrue(bs.bitSet(1))
assertTrue(bs[1])
assertTrue(!bs.bitSet(1))
assertTrue(!bs.bitSet(0))
assertTrue(bs[0])
assertTrue(bs.bitClear(0))
assertTrue(!bs.bitClear(0))
assertTrue(bs[1])
}
}
class LockFreeIntBits {
private val bits = atomic(0)
private fun Int.mask() = 1 shl this
operator fun get(index: Int): Boolean = bits.value and index.mask() != 0
// User-defined private inline function
private inline fun bitUpdate(check: (Int) -> Boolean, upd: (Int) -> Int): Boolean {
bits.update {
if (check(it)) return false
upd(it)
}
return true
}
fun bitSet(index: Int): Boolean {
val mask = index.mask()
return bitUpdate({ it and mask != 0 }, { it or mask })
}
fun bitClear(index: Int): Boolean {
val mask = index.mask()
return bitUpdate({ it and mask == 0 }, { it and mask.inv() })
}
}
fun box(): String {
val testClass = LockFreeIntBitsTest()
testClass.testBasic()
return "OK"
}
@@ -0,0 +1,30 @@
@kotlin.Metadata
public final class LockFreeIntBits {
// source: 'LockFreeIntBitsTest.kt'
private synthetic final static field bits$volatile$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private synthetic volatile field bits$volatile: int
static method <clinit>(): void
public method <init>(): void
public final method bitClear(p0: int): boolean
public final method bitSet(p0: int): boolean
private final method bitUpdate(p0: kotlin.jvm.functions.Function1, p1: kotlin.jvm.functions.Function1): boolean
public final method get(p0: int): boolean
private synthetic final static method getBits$volatile$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private synthetic final method getBits$volatile(): int
private final method mask(p0: int): int
private synthetic final method setBits$volatile(p0: int): void
private synthetic final method update$atomicfu(p0: java.util.concurrent.atomic.AtomicIntegerFieldUpdater, p1: kotlin.jvm.functions.Function1, p2: java.lang.Object): void
}
@kotlin.Metadata
public final class LockFreeIntBitsTest {
// source: 'LockFreeIntBitsTest.kt'
public method <init>(): void
public final method testBasic(): void
}
@kotlin.Metadata
public final class LockFreeIntBitsTestKt {
// source: 'LockFreeIntBitsTest.kt'
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
}
@@ -0,0 +1,29 @@
import kotlinx.atomicfu.*
import kotlin.test.*
class LockTest {
private val inProgressLock = atomic(false)
fun testLock() {
var result = ""
if (inProgressLock.tryAcquire()) {
result = "OK"
}
assertEquals("OK", result)
}
}
// This function will be removed by transformer
@Suppress("NOTHING_TO_INLINE")
private inline fun AtomicBoolean.tryAcquire(): Boolean = compareAndSet(false, true)
// This function is here to test if the Kotlin metadata still consistent after transform
// It is used in ReflectionTest, DO NOT REMOVE
@Suppress("UNUSED_PARAMETER")
fun <AA, BB : Number> String.reflectionTest(mapParam: Map<in AA, BB>): List<BB> = error("no impl")
fun box(): String {
val testClass = LockTest()
testClass.testLock()
return "OK"
}
@@ -0,0 +1,21 @@
@kotlin.Metadata
public final class LockTest {
// source: 'LockTest.kt'
private synthetic final static field inProgressLock$volatile$FU: java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private synthetic volatile field inProgressLock$volatile: int
static method <clinit>(): void
public method <init>(): void
private synthetic final static method getInProgressLock$volatile$FU(): java.util.concurrent.atomic.AtomicIntegerFieldUpdater
private synthetic final method getInProgressLock$volatile(): int
private synthetic final method setInProgressLock$volatile(p0: int): void
public final method testLock(): void
}
@kotlin.Metadata
public final class LockTestKt {
// source: 'LockTest.kt'
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
public final static @org.jetbrains.annotations.NotNull method reflectionTest(@org.jetbrains.annotations.NotNull p0: java.lang.String, @org.jetbrains.annotations.NotNull p1: java.util.Map): java.util.List
private synthetic final static method tryAcquire$atomicfu$array(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerArray, p2: int): boolean
private synthetic final static method tryAcquire$atomicfu(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicIntegerFieldUpdater): boolean
}
@@ -0,0 +1,27 @@
import kotlinx.atomicfu.*
import kotlin.test.*
class ParameterizedInlineFunExtensionTest {
private inline fun <S> AtomicRef<S>.foo(res1: S, res2: S, foo: (S) -> S): S {
val res = bar(res1, res2)
return res
}
private inline fun <S> AtomicRef<S>.bar(res1: S, res2: S): S {
return res2
}
private val tail = atomic("aaa")
fun testClose() {
val res = tail.foo("bbb", "ccc") { s -> s }
assertEquals("ccc", res)
}
}
fun box(): String {
val testClass = ParameterizedInlineFunExtensionTest()
testClass.testClose()
return "OK"
}
@@ -0,0 +1,22 @@
@kotlin.Metadata
public final class ParameterizedInlineFunExtensionTest {
// source: 'ParameterizedInlineFunExtensionTest.kt'
private synthetic final static field tail$volatile$FU: java.util.concurrent.atomic.AtomicReferenceFieldUpdater
private synthetic volatile field tail$volatile: java.lang.Object
static method <clinit>(): void
public method <init>(): void
private synthetic final method bar$atomicfu$array(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicReferenceArray, p2: int, p3: java.lang.Object, p4: java.lang.Object): java.lang.Object
private synthetic final method bar$atomicfu(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicReferenceFieldUpdater, p2: java.lang.Object, p3: java.lang.Object): java.lang.Object
private synthetic final method foo$atomicfu$array(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicReferenceArray, p2: int, p3: java.lang.Object, p4: java.lang.Object, p5: kotlin.jvm.functions.Function1): java.lang.Object
private synthetic final method foo$atomicfu(p0: java.lang.Object, p1: java.util.concurrent.atomic.AtomicReferenceFieldUpdater, p2: java.lang.Object, p3: java.lang.Object, p4: kotlin.jvm.functions.Function1): java.lang.Object
private synthetic final static method getTail$volatile$FU(): java.util.concurrent.atomic.AtomicReferenceFieldUpdater
private synthetic final method getTail$volatile(): java.lang.Object
private synthetic final method setTail$volatile(p0: java.lang.Object): void
public final method testClose(): void
}
@kotlin.Metadata
public final class ParameterizedInlineFunExtensionTestKt {
// source: 'ParameterizedInlineFunExtensionTest.kt'
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
}