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