xref: /aosp_15_r20/external/kotlinx.atomicfu/atomicfu/src/nativeMain/kotlin/kotlinx/atomicfu/AtomicFU.kt (revision 68017707106cb9da9fed635c150bc497c09c160f)
1 /*
2  * Copyright 2017-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3  */
4 
5 @file:Suppress(
6     "NOTHING_TO_INLINE",
7     "RedundantVisibilityModifier",
8     "CanBePrimaryConstructorProperty",
9     "INVISIBLE_REFERENCE",
10     "INVISIBLE_MEMBER"
11 )
12 
13 package kotlinx.atomicfu
14 
15 import kotlin.concurrent.AtomicInt as KAtomicInt
16 import kotlin.concurrent.AtomicLong as KAtomicLong
17 import kotlin.concurrent.AtomicReference as KAtomicRef
18 import kotlin.native.concurrent.isFrozen
19 import kotlin.native.concurrent.freeze
20 import kotlin.reflect.KProperty
21 import kotlinx.atomicfu.TraceBase.None
22 import kotlin.internal.InlineOnly
23 
atomicnull24 public actual fun <T> atomic(initial: T, trace: TraceBase): AtomicRef<T> = AtomicRef<T>(KAtomicRef(initial))
25 public actual fun <T> atomic(initial: T): AtomicRef<T> = atomic(initial, None)
26 public actual fun atomic(initial: Int, trace: TraceBase): AtomicInt = AtomicInt(KAtomicInt(initial))
27 public actual fun atomic(initial: Int): AtomicInt = atomic(initial, None)
28 public actual fun atomic(initial: Long, trace: TraceBase): AtomicLong = AtomicLong(KAtomicLong(initial))
29 public actual fun atomic(initial: Long): AtomicLong = atomic(initial, None)
30 public actual fun atomic(initial: Boolean, trace: TraceBase): AtomicBoolean = AtomicBoolean(KAtomicInt(if (initial) 1 else 0))
31 public actual fun atomic(initial: Boolean): AtomicBoolean = atomic(initial, None)
32 
33 // ==================================== AtomicRef ====================================
34 
35 @Suppress("ACTUAL_WITHOUT_EXPECT")
36 public actual class AtomicRef<T> internal constructor(@PublishedApi internal val a: KAtomicRef<T>) {
37     public actual inline var value: T
38         get() = a.value
39         set(value) {
40             if (a.isFrozen) value.freeze()
41             a.value = value
42         }
43 
44     @InlineOnly
45     public actual inline operator fun getValue(thisRef: Any?, property: KProperty<*>): T = value
46 
47     @InlineOnly
48     public actual inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { this.value = value }
49 
50     public actual inline fun lazySet(value: T) {
51         if (a.isFrozen) value.freeze()
52         a.value = value
53     }
54 
55     public actual inline fun compareAndSet(expect: T, update: T): Boolean {
56         if (a.isFrozen) update.freeze()
57         return a.compareAndSet(expect, update)
58     }
59 
60     public actual fun getAndSet(value: T): T {
61         if (a.isFrozen) value.freeze()
62         while (true) {
63             val cur = a.value
64             if (cur === value) return cur
65             if (a.compareAndExchange(cur, value) === cur) return cur
66         }
67     }
68 
69     override fun toString(): String = value.toString()
70 }
71 
72 // ==================================== AtomicBoolean ====================================
73 
74 @Suppress("ACTUAL_WITHOUT_EXPECT")
75 public actual class AtomicBoolean internal constructor(@PublishedApi internal val a: KAtomicInt) {
76     public actual inline var value: Boolean
77         get() = a.value != 0
78         set(value) { a.value = if (value) 1 else 0 }
79 
getValuenull80     public actual inline operator fun getValue(thisRef: Any?, property: KProperty<*>): Boolean = value
81 
82     public actual inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean) { this.value = value }
83 
lazySetnull84     public actual inline fun lazySet(value: Boolean) { this.value = value }
85 
compareAndSetnull86     public actual fun compareAndSet(expect: Boolean, update: Boolean): Boolean {
87         val iExpect = if (expect) 1 else 0
88         val iUpdate = if (update) 1 else 0
89         return a.compareAndSet(iExpect, iUpdate)
90     }
91 
getAndSetnull92     public actual fun getAndSet(value: Boolean): Boolean {
93         val iValue = if (value) 1 else 0
94         while (true) {
95             val cur = a.value
96             if (cur == iValue) return value
97             if (a.compareAndSet(cur, iValue)) return cur != 0
98         }
99     }
100 
toStringnull101     override fun toString(): String = value.toString()
102 }
103 
104 // ==================================== AtomicInt ====================================
105 
106 @Suppress("ACTUAL_WITHOUT_EXPECT")
107 public actual class AtomicInt internal constructor(@PublishedApi internal val a: KAtomicInt) {
108     public actual inline var value: Int
109         get() = a.value
110         set(value) { a.value = value }
111 
112     @InlineOnly
113     actual inline operator fun getValue(thisRef: Any?, property: KProperty<*>): Int = value
114 
115     @InlineOnly
116     public actual inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { this.value = value }
117 
118     public actual inline fun lazySet(value: Int) { a.value = value }
119 
120     public actual inline fun compareAndSet(expect: Int, update: Int): Boolean =
121         a.compareAndSet(expect, update)
122 
123     public actual fun getAndSet(value: Int): Int {
124         while (true) {
125             val cur = a.value
126             if (cur == value) return cur
127             if (a.compareAndSet(cur, value)) return cur
128         }
129     }
130 
131     public actual inline fun getAndIncrement(): Int = a.addAndGet(1) - 1
132     public actual inline fun getAndDecrement(): Int = a.addAndGet(-1) + 1
133     public actual inline fun getAndAdd(delta: Int): Int = a.addAndGet(delta) - delta
134     public actual inline fun addAndGet(delta: Int): Int = a.addAndGet(delta)
135     public actual inline fun incrementAndGet(): Int = a.addAndGet(1)
136     public actual inline fun decrementAndGet(): Int = a.addAndGet(-1)
137 
138     public actual inline operator fun plusAssign(delta: Int) { getAndAdd(delta) }
139     public actual inline operator fun minusAssign(delta: Int) { getAndAdd(-delta) }
140 
141     override fun toString(): String = value.toString()
142 }
143 
144 // ==================================== AtomicLong ====================================
145 
146 @Suppress("ACTUAL_WITHOUT_EXPECT")
147 public actual class AtomicLong internal constructor(@PublishedApi internal val a: KAtomicLong) {
148     public actual inline var value: Long
149         get() = a.value
150         set(value) { a.value = value }
151 
getValuenull152     public actual inline operator fun getValue(thisRef: Any?, property: KProperty<*>): Long = value
153 
154     public actual inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Long) { this.value = value }
155 
lazySetnull156     public actual inline fun lazySet(value: Long) { a.value = value }
157 
compareAndSetnull158     public actual inline fun compareAndSet(expect: Long, update: Long): Boolean =
159         a.compareAndSet(expect, update)
160 
161     public actual fun getAndSet(value: Long): Long {
162         while (true) {
163             val cur = a.value
164             if (cur == value) return cur
165             if (a.compareAndSet(cur, value)) return cur
166         }
167     }
168 
getAndIncrementnull169     public actual inline fun getAndIncrement(): Long = a.addAndGet(1L) - 1
170     public actual inline fun getAndDecrement(): Long = a.addAndGet(-1L) + 1
171     public actual inline fun getAndAdd(delta: Long): Long = a.addAndGet(delta) - delta
172     public actual inline fun addAndGet(delta: Long): Long = a.addAndGet(delta)
173     public actual inline fun incrementAndGet(): Long = a.addAndGet(1L)
174     public actual inline fun decrementAndGet(): Long = a.addAndGet(-1L)
175 
176     public actual inline operator fun plusAssign(delta: Long) { getAndAdd(delta) }
minusAssignnull177     public actual inline operator fun minusAssign(delta: Long) { getAndAdd(-delta) }
178 
toStringnull179     override fun toString(): String = value.toString()
180 }
181 
182