xref: /aosp_15_r20/external/kotlinx.atomicfu/atomicfu/src/commonMain/kotlin/kotlinx/atomicfu/AtomicFU.common.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("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
6 
7 package kotlinx.atomicfu
8 
9 import kotlin.internal.InlineOnly
10 import kotlinx.atomicfu.TraceBase.None
11 import kotlin.reflect.KProperty
12 
13 /**
14  * Creates atomic reference with a given [initial] value and a [trace] object to [trace modifications][Trace] of the value.
15  *
16  * It can only be used to initialize a private or internal read-only property, like this:
17  *
18  * ```
19  * private val f = atomic<Type>(initial, trace)
20  * ```
21  */
atomicnull22 public expect fun <T> atomic(initial: T, trace: TraceBase = None): AtomicRef<T>
23 
24 // Binary compatibility with IR, should be removed with Kotlin 1.5 release
25 
26 /**
27  * Creates atomic reference with a given [initial] value.
28  *
29  * It can only be used to initialize a private or internal read-only property, like this:
30  *
31  * ```
32  * private val f = atomic<Type>(initial)
33  * ```
34  */
35 public expect fun <T> atomic(initial: T): AtomicRef<T>
36 
37 /**
38  * Creates atomic [Int] with a given [initial] value and a [trace] object to [trace modifications][Trace] of the value.
39  *
40  * It can only be used to initialize a private or internal read-only property, like this:
41  *
42  * ```
43  * private val f = atomic(initialInt, trace)
44  * ```
45  */
46 public expect fun atomic(initial: Int, trace: TraceBase = None): AtomicInt
47 
48 // Binary compatibility with IR, should be removed with Kotlin 1.5 release
49 
50 /**
51  * Creates atomic [Int] with a given [initial] value.
52  *
53  * It can only be used to initialize a private or internal read-only property, like this:
54  *
55  * ```
56  * private val f = atomic(initialInt)
57  * ```
58  */
59 public expect fun atomic(initial: Int): AtomicInt
60 
61 /**
62  * Creates atomic [Long] with a given [initial] value and a [trace] object to [trace modifications][Trace] of the value.
63  *
64  * It can only be used to initialize a private or internal read-only property, like this:
65  *
66  * ```
67  * private val f = atomic(initialLong, trace)
68  * ```
69  */
70 public expect fun atomic(initial: Long, trace: TraceBase = None): AtomicLong
71 
72 // Binary compatibility with IR, should be removed with Kotlin 1.5 release
73 
74 /**
75  * Creates atomic [Long] with a given [initial] value.
76  *
77  * It can only be used to initialize a private or internal read-only property, like this:
78  *
79  * ```
80  * private val f = atomic(initialLong)
81  * ```
82  */
83 public expect fun atomic(initial: Long): AtomicLong
84 
85 /**
86  * Creates atomic [Boolean] with a given [initial] value and a [trace] object to [trace modifications][Trace] of the value.
87  *
88  * It can only be used to initialize a private or internal read-only property, like this:
89  *
90  * ```
91  * private val f = atomic(initialBoolean, trace)
92  * ```
93  */
94 public expect fun atomic(initial: Boolean, trace: TraceBase = None): AtomicBoolean
95 
96 // Binary compatibility with IR, should be removed with Kotlin 1.5 release
97 
98 /**
99  * Creates atomic [Boolean] with a given [initial] value.
100  *
101  * It can only be used to initialize a private or internal read-only property, like this:
102  *
103  * ```
104  * private val f = atomic(initialBoolean)
105  * ```
106  */
107 public expect fun atomic(initial: Boolean): AtomicBoolean
108 
109 /**
110  * Creates array of AtomicRef<T> of specified size, where each element is initialised with null value
111  */
112 @OptionalJsName(ATOMIC_ARRAY_OF_NULLS)
113 public fun <T> atomicArrayOfNulls(size: Int): AtomicArray<T?> = AtomicArray(size)
114 
115 // ==================================== AtomicRef ====================================
116 
117 /**
118  * Atomic reference to a variable of type [T] with volatile reads/writes via
119  * [value] property and various atomic read-modify-write operations
120  * like [compareAndSet] and others.
121  */
122 public expect class AtomicRef<T> {
123     /**
124      * Reading/writing this property maps to read/write of volatile variable.
125      */
126     public var value: T
127 
128     @InlineOnly
129     public inline operator fun getValue(thisRef: Any?, property: KProperty<*>): T
130 
131     @InlineOnly
132     public inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T)
133 
134     /**
135      * Maps to [AtomicReferenceFieldUpdater.lazySet].
136      */
137     public fun lazySet(value: T)
138 
139     /**
140      * Maps to [AtomicReferenceFieldUpdater.compareAndSet].
141      */
142     public fun compareAndSet(expect: T, update: T): Boolean
143 
144     /**
145      * Maps to [AtomicReferenceFieldUpdater.getAndSet].
146      */
147     public fun getAndSet(value: T): T
148 }
149 
150 /**
151  * Infinite loop that reads this atomic variable and performs the specified [action] on its value.
152  */
loopnull153 public inline fun <T> AtomicRef<T>.loop(action: (T) -> Unit): Nothing {
154     while (true) {
155         action(value)
156     }
157 }
158 
159 /**
160  * Updates variable atomically using the specified [function] of its value.
161  */
updatenull162 public inline fun <T> AtomicRef<T>.update(function: (T) -> T) {
163     while (true) {
164         val cur = value
165         val upd = function(cur)
166         if (compareAndSet(cur, upd)) return
167     }
168 }
169 
170 /**
171  * Updates variable atomically using the specified [function] of its value and returns its old value.
172  */
getAndUpdatenull173 public inline fun <T> AtomicRef<T>.getAndUpdate(function: (T) -> T): T {
174     while (true) {
175         val cur = value
176         val upd = function(cur)
177         if (compareAndSet(cur, upd)) return cur
178     }
179 }
180 
181 /**
182  * Updates variable atomically using the specified [function] of its value and returns its new value.
183  */
updateAndGetnull184 public inline fun <T> AtomicRef<T>.updateAndGet(function: (T) -> T): T {
185     while (true) {
186         val cur = value
187         val upd = function(cur)
188         if (compareAndSet(cur, upd)) return upd
189     }
190 }
191 
192 
193 // ==================================== AtomicBoolean ====================================
194 
195 /**
196  * Atomic reference to a [Boolean] variable with volatile reads/writes via
197  * [value] property and various atomic read-modify-write operations
198  * like [compareAndSet] and others.
199  */
200 public expect class AtomicBoolean {
201     /**
202      * Reading/writing this property maps to read/write of volatile variable.
203      */
204     public var value: Boolean
205 
206     @InlineOnly
getValuenull207     public inline operator fun getValue(thisRef: Any?, property: KProperty<*>): Boolean
208 
209     @InlineOnly
210     public inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean)
211 
212     /**
213      * Maps to [AtomicIntegerFieldUpdater.lazySet].
214      */
215     public fun lazySet(value: Boolean)
216 
217     /**
218      * Maps to [AtomicIntegerFieldUpdater.compareAndSet].
219      */
220     public fun compareAndSet(expect: Boolean, update: Boolean): Boolean
221 
222     /**
223      * Maps to [AtomicIntegerFieldUpdater.getAndSet].
224      */
225     public fun getAndSet(value: Boolean): Boolean
226 
227 }
228 
229 /**
230  * Infinite loop that reads this atomic variable and performs the specified [action] on its value.
231  */
232 public inline fun AtomicBoolean.loop(action: (Boolean) -> Unit): Nothing {
233     while (true) {
234         action(value)
235     }
236 }
237 
238 /**
239  * Updates variable atomically using the specified [function] of its value.
240  */
updatenull241 public inline fun AtomicBoolean.update(function: (Boolean) -> Boolean) {
242     while (true) {
243         val cur = value
244         val upd = function(cur)
245         if (compareAndSet(cur, upd)) return
246     }
247 }
248 
249 /**
250  * Updates variable atomically using the specified [function] of its value and returns its old value.
251  */
getAndUpdatenull252 public inline fun AtomicBoolean.getAndUpdate(function: (Boolean) -> Boolean): Boolean {
253     while (true) {
254         val cur = value
255         val upd = function(cur)
256         if (compareAndSet(cur, upd)) return cur
257     }
258 }
259 
260 /**
261  * Updates variable atomically using the specified [function] of its value and returns its new value.
262  */
updateAndGetnull263 public inline fun AtomicBoolean.updateAndGet(function: (Boolean) -> Boolean): Boolean {
264     while (true) {
265         val cur = value
266         val upd = function(cur)
267         if (compareAndSet(cur, upd)) return upd
268     }
269 }
270 
271 // ==================================== AtomicInt ====================================
272 
273 /**
274  * Atomic reference to an [Int] variable with volatile reads/writes via
275  * [value] property and various atomic read-modify-write operations
276  * like [compareAndSet] and others.
277  */
278 public expect class AtomicInt {
279     /**
280      * Reads/writes of this property maps to read/write of volatile variable.
281      */
282     public var value: Int
283 
284     @InlineOnly
getValuenull285     public inline operator fun getValue(thisRef: Any?, property: KProperty<*>): Int
286 
287     @InlineOnly
288     public inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int)
289 
290     /**
291      * Maps to [AtomicIntegerFieldUpdater.lazySet].
292      */
293     public fun lazySet(value: Int)
294 
295     /**
296      * Maps to [AtomicIntegerFieldUpdater.compareAndSet].
297      */
298     public fun compareAndSet(expect: Int, update: Int): Boolean
299 
300     /**
301      * Maps to [AtomicIntegerFieldUpdater.getAndSet].
302      */
303     public fun getAndSet(value: Int): Int
304 
305     /**
306      * Maps to [AtomicIntegerFieldUpdater.getAndIncrement].
307      */
308     public fun getAndIncrement(): Int
309 
310     /**
311      * Maps to [AtomicIntegerFieldUpdater.getAndDecrement].
312      */
313     public fun getAndDecrement(): Int
314 
315     /**
316      * Maps to [AtomicIntegerFieldUpdater.getAndAdd].
317      */
318     public fun getAndAdd(delta: Int): Int
319 
320     /**
321      * Maps to [AtomicIntegerFieldUpdater.addAndGet].
322      */
323     public fun addAndGet(delta: Int): Int
324 
325     /**
326      * Maps to [AtomicIntegerFieldUpdater.incrementAndGet].
327      */
328     public fun incrementAndGet(): Int
329 
330     /**
331      * Maps to [AtomicIntegerFieldUpdater.decrementAndGet].
332      */
333     public fun decrementAndGet(): Int
334 
335     /**
336      * Performs atomic addition of [delta].
337      */
338     public inline operator fun plusAssign(delta: Int)
339 
340     /**
341      * Performs atomic subtraction of [delta].
342      */
343     public inline operator fun minusAssign(delta: Int)
344 }
345 
346 /**
347  * Infinite loop that reads this atomic variable and performs the specified [action] on its value.
348  */
349 public inline fun AtomicInt.loop(action: (Int) -> Unit): Nothing {
350     while (true) {
351         action(value)
352     }
353 }
354 
355 /**
356  * Updates variable atomically using the specified [function] of its value.
357  */
updatenull358 public inline fun AtomicInt.update(function: (Int) -> Int) {
359     while (true) {
360         val cur = value
361         val upd = function(cur)
362         if (compareAndSet(cur, upd)) return
363     }
364 }
365 
366 /**
367  * Updates variable atomically using the specified [function] of its value and returns its old value.
368  */
getAndUpdatenull369 public inline fun AtomicInt.getAndUpdate(function: (Int) -> Int): Int {
370     while (true) {
371         val cur = value
372         val upd = function(cur)
373         if (compareAndSet(cur, upd)) return cur
374     }
375 }
376 
377 /**
378  * Updates variable atomically using the specified [function] of its value and returns its new value.
379  */
updateAndGetnull380 public inline fun AtomicInt.updateAndGet(function: (Int) -> Int): Int {
381     while (true) {
382         val cur = value
383         val upd = function(cur)
384         if (compareAndSet(cur, upd)) return upd
385     }
386 }
387 
388 // ==================================== AtomicLong ====================================
389 
390 /**
391  * Atomic reference to a [Long] variable with volatile reads/writes via
392  * [value] property and various atomic read-modify-write operations
393  * like [compareAndSet] and others.
394  */
395 public expect class AtomicLong {
396     /**
397      * Reads/writes of this property maps to read/write of volatile variable.
398      */
399     public var value: Long
400 
401     @InlineOnly
getValuenull402     public operator fun getValue(thisRef: Any?, property: KProperty<*>): Long
403 
404     @InlineOnly
405     public operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Long)
406 
407     /**
408      * Maps to [AtomicLongFieldUpdater.lazySet].
409      */
410     public fun lazySet(value: Long)
411 
412     /**
413      * Maps to [AtomicLongFieldUpdater.compareAndSet].
414      */
415     public fun compareAndSet(expect: Long, update: Long): Boolean
416 
417     /**
418      * Maps to [AtomicLongFieldUpdater.getAndSet].
419      */
420     public fun getAndSet(value: Long): Long
421 
422     /**
423      * Maps to [AtomicLongFieldUpdater.getAndIncrement].
424      */
425     public fun getAndIncrement(): Long
426 
427     /**
428      * Maps to [AtomicLongFieldUpdater.getAndDecrement].
429      */
430     public fun getAndDecrement(): Long
431 
432     /**
433      * Maps to [AtomicLongFieldUpdater.getAndAdd].
434      */
435     public fun getAndAdd(delta: Long): Long
436 
437     /**
438      * Maps to [AtomicLongFieldUpdater.addAndGet].
439      */
440     public fun addAndGet(delta: Long): Long
441 
442     /**
443      * Maps to [AtomicLongFieldUpdater.incrementAndGet].
444      */
445     public fun incrementAndGet(): Long
446 
447     /**
448      * Maps to [AtomicLongFieldUpdater.decrementAndGet].
449      */
450     public fun decrementAndGet(): Long
451 
452     /**
453      * Performs atomic addition of [delta].
454      */
455     public inline operator fun plusAssign(delta: Long)
456 
457     /**
458      * Performs atomic subtraction of [delta].
459      */
460     public inline operator fun minusAssign(delta: Long)
461 }
462 
463 /**
464  * Infinite loop that reads this atomic variable and performs the specified [action] on its value.
465  */
466 public inline fun AtomicLong.loop(action: (Long) -> Unit): Nothing {
467     while (true) {
468         action(value)
469     }
470 }
471 
472 /**
473  * Updates variable atomically using the specified [function] of its value.
474  */
updatenull475 public inline fun AtomicLong.update(function: (Long) -> Long) {
476     while (true) {
477         val cur = value
478         val upd = function(cur)
479         if (compareAndSet(cur, upd)) return
480     }
481 }
482 
483 /**
484  * Updates variable atomically using the specified [function] of its value and returns its old value.
485  */
getAndUpdatenull486 public inline fun AtomicLong.getAndUpdate(function: (Long) -> Long): Long {
487     while (true) {
488         val cur = value
489         val upd = function(cur)
490         if (compareAndSet(cur, upd)) return cur
491     }
492 }
493 
494 /**
495  * Updates variable atomically using the specified [function] of its value and returns its new value.
496  */
updateAndGetnull497 public inline fun AtomicLong.updateAndGet(function: (Long) -> Long): Long {
498     while (true) {
499         val cur = value
500         val upd = function(cur)
501         if (compareAndSet(cur, upd)) return upd
502     }
503 }
504 
505 // ==================================== AtomicIntArray ====================================
506 
507 /**
508  * Creates a new array of AtomicInt values of the specified size, where each element is initialised with 0
509  */
510 @OptionalJsName(ATOMIC_INT_ARRAY)
511 public class AtomicIntArray(size: Int) {
<lambda>null512     private val array = Array(size) { atomic(0) }
513 
514     @OptionalJsName(ARRAY_SIZE)
515     public val size: Int
516         get() = array.size
517 
518     @OptionalJsName(ARRAY_ELEMENT_GET)
getnull519     public operator fun get(index: Int): AtomicInt = array[index]
520 }
521 
522 // ==================================== AtomicLongArray ====================================
523 
524 /**
525  * Creates a new array of AtomicLong values of the specified size, where each element is initialised with 0L
526  */
527 @OptionalJsName(ATOMIC_LONG_ARRAY)
528 public class AtomicLongArray(size: Int) {
529     private val array = Array(size) { atomic(0L) }
530 
531     @OptionalJsName(ARRAY_SIZE)
532     public val size: Int
533         get() = array.size
534 
535     @OptionalJsName(ARRAY_ELEMENT_GET)
536     public operator fun get(index: Int): AtomicLong = array[index]
537 }
538 
539 // ==================================== AtomicBooleanArray ====================================
540 
541 /**
542  * Creates a new array of AtomicBoolean values of the specified size, where each element is initialised with false
543  */
544 @OptionalJsName(ATOMIC_BOOLEAN_ARRAY)
545 public class AtomicBooleanArray(size: Int) {
<lambda>null546     private val array = Array(size) { atomic(false) }
547 
548     @OptionalJsName(ARRAY_SIZE)
549     public val size: Int
550         get() = array.size
551 
552     @OptionalJsName(ARRAY_ELEMENT_GET)
getnull553     public operator fun get(index: Int): AtomicBoolean = array[index]
554 }
555 
556 
557 // ==================================== AtomicArray ====================================
558 
559 @OptionalJsName(ATOMIC_REF_ARRAY)
560 public class AtomicArray<T> internal constructor(size: Int) {
561     private val array = Array(size) { atomic<T?>(null) }
562 
563     @OptionalJsName(ARRAY_SIZE)
564     public val size: Int
565         get() = array.size
566 
567     @OptionalJsName(ARRAY_ELEMENT_GET)
568     public operator fun get(index: Int): AtomicRef<T?> = array[index]
569 }
570