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