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