• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package kotlinx.atomicfu
6 
7 import kotlin.js.JsName
8 
9 /**
10  * Creates atomic reference with a given [initial] value.
11  *
12  * It can only be used in initialize of private read-only property, like this:
13  *
14  * ```
15  * private val f = atomic<Type>(initial)
16  * ```
17  */
atomicnull18 public expect fun <T> atomic(initial: T): AtomicRef<T>
19 
20 /**
21  * Creates atomic [Int] with a given [initial] value.
22  *
23  * It can only be used in initialize of private read-only property, like this:
24  *
25  * ```
26  * private val f = atomic(initialInt)
27  * ```
28  */
29 public expect fun atomic(initial: Int): AtomicInt
30 
31 /**
32  * Creates atomic [Long] with a given [initial] value.
33  *
34  * It can only be used in initialize of private read-only property, like this:
35  *
36  * ```
37  * private val f = atomic(initialLong)
38  * ```
39  */
40 public expect fun atomic(initial: Long): AtomicLong
41 
42 /**
43  * Creates atomic [Boolean] with a given [initial] value.
44  *
45  * It can only be used in initialize of private read-only property, like this:
46  *
47  * ```
48  * private val f = atomic(initialBoolean)
49  * ```
50  */
51 public expect fun atomic(initial: Boolean): AtomicBoolean
52 
53 /**
54  * Creates array of AtomicRef<T> of specified size, where each element is initialised with null value
55  */
56 @JsName("AtomicLongArray\$ofNulls")
57 public fun <T> atomicArrayOfNulls(size: Int): AtomicArray<T?> = AtomicArray(size)
58 
59 // ==================================== AtomicRef ====================================
60 
61 /**
62  * Atomic reference to a variable of type [T] with volatile reads/writes via
63  * [value] property and various atomic read-modify-write operations
64  * like [compareAndSet] and others.
65  */
66 public expect class AtomicRef<T> {
67     /**
68      * Reading/writing this property maps to read/write of volatile variable.
69      */
70     public var value: T
71 
72     /**
73      * Maps to [AtomicReferenceFieldUpdater.lazySet].
74      */
75     public fun lazySet(value: T)
76 
77     /**
78      * Maps to [AtomicReferenceFieldUpdater.compareAndSet].
79      */
80     public fun compareAndSet(expect: T, update: T): Boolean
81 
82     /**
83      * Maps to [AtomicReferenceFieldUpdater.getAndSet].
84      */
85     public fun getAndSet(value: T): T
86 }
87 
88 /**
89  * Infinite loop that reads this atomic variable and performs the specified [action] on its value.
90  */
loopnull91 public inline fun <T> AtomicRef<T>.loop(action: (T) -> Unit): Nothing {
92     while (true) {
93         action(value)
94     }
95 }
96 
97 /**
98  * Updates variable atomically using the specified [function] of its value.
99  */
updatenull100 public inline fun <T> AtomicRef<T>.update(function: (T) -> T) {
101     while (true) {
102         val cur = value
103         val upd = function(cur)
104         if (compareAndSet(cur, upd)) return
105     }
106 }
107 
108 /**
109  * Updates variable atomically using the specified [function] of its value and returns its old value.
110  */
getAndUpdatenull111 public inline fun <T> AtomicRef<T>.getAndUpdate(function: (T) -> T): T {
112     while (true) {
113         val cur = value
114         val upd = function(cur)
115         if (compareAndSet(cur, upd)) return cur
116     }
117 }
118 
119 /**
120  * Updates variable atomically using the specified [function] of its value and returns its new value.
121  */
updateAndGetnull122 public inline fun <T> AtomicRef<T>.updateAndGet(function: (T) -> T): T {
123     while (true) {
124         val cur = value
125         val upd = function(cur)
126         if (compareAndSet(cur, upd)) return upd
127     }
128 }
129 
130 
131 // ==================================== AtomicBoolean ====================================
132 
133 /**
134  * Atomic reference to a [Boolean] variable with volatile reads/writes via
135  * [value] property and various atomic read-modify-write operations
136  * like [compareAndSet] and others.
137  */
138 public expect class AtomicBoolean {
139     /**
140      * Reading/writing this property maps to read/write of volatile variable.
141      */
142     public var value: Boolean
143 
144     /**
145      * Maps to [AtomicIntegerFieldUpdater.lazySet].
146      */
lazySetnull147     public fun lazySet(value: Boolean)
148 
149     /**
150      * Maps to [AtomicIntegerFieldUpdater.compareAndSet].
151      */
152     public fun compareAndSet(expect: Boolean, update: Boolean): Boolean
153 
154     /**
155      * Maps to [AtomicIntegerFieldUpdater.getAndSet].
156      */
157     public fun getAndSet(value: Boolean): Boolean
158 
159 }
160 
161 /**
162  * Infinite loop that reads this atomic variable and performs the specified [action] on its value.
163  */
164 public inline fun AtomicBoolean.loop(action: (Boolean) -> Unit): Nothing {
165     while (true) {
166         action(value)
167     }
168 }
169 
170 /**
171  * Updates variable atomically using the specified [function] of its value.
172  */
updatenull173 public inline fun AtomicBoolean.update(function: (Boolean) -> Boolean) {
174     while (true) {
175         val cur = value
176         val upd = function(cur)
177         if (compareAndSet(cur, upd)) return
178     }
179 }
180 
181 /**
182  * Updates variable atomically using the specified [function] of its value and returns its old value.
183  */
getAndUpdatenull184 public inline fun AtomicBoolean.getAndUpdate(function: (Boolean) -> Boolean): Boolean {
185     while (true) {
186         val cur = value
187         val upd = function(cur)
188         if (compareAndSet(cur, upd)) return cur
189     }
190 }
191 
192 /**
193  * Updates variable atomically using the specified [function] of its value and returns its new value.
194  */
updateAndGetnull195 public inline fun AtomicBoolean.updateAndGet(function: (Boolean) -> Boolean): Boolean {
196     while (true) {
197         val cur = value
198         val upd = function(cur)
199         if (compareAndSet(cur, upd)) return upd
200     }
201 }
202 
203 // ==================================== AtomicInt ====================================
204 
205 /**
206  * Atomic reference to an [Int] variable with volatile reads/writes via
207  * [value] property and various atomic read-modify-write operations
208  * like [compareAndSet] and others.
209  */
210 public expect class AtomicInt {
211     /**
212      * Reads/writes of this property maps to read/write of volatile variable.
213      */
214     public var value: Int
215 
216     /**
217      * Maps to [AtomicIntegerFieldUpdater.lazySet].
218      */
lazySetnull219     public fun lazySet(value: Int)
220 
221     /**
222      * Maps to [AtomicIntegerFieldUpdater.compareAndSet].
223      */
224     public fun compareAndSet(expect: Int, update: Int): Boolean
225 
226     /**
227      * Maps to [AtomicIntegerFieldUpdater.getAndSet].
228      */
229     public fun getAndSet(value: Int): Int
230 
231     /**
232      * Maps to [AtomicIntegerFieldUpdater.getAndIncrement].
233      */
234     public fun getAndIncrement(): Int
235 
236     /**
237      * Maps to [AtomicIntegerFieldUpdater.getAndDecrement].
238      */
239     public fun getAndDecrement(): Int
240 
241     /**
242      * Maps to [AtomicIntegerFieldUpdater.getAndAdd].
243      */
244     public fun getAndAdd(delta: Int): Int
245 
246     /**
247      * Maps to [AtomicIntegerFieldUpdater.addAndGet].
248      */
249     public fun addAndGet(delta: Int): Int
250 
251     /**
252      * Maps to [AtomicIntegerFieldUpdater.incrementAndGet].
253      */
254     public fun incrementAndGet(): Int
255 
256     /**
257      * Maps to [AtomicIntegerFieldUpdater.decrementAndGet].
258      */
259     public fun decrementAndGet(): Int
260 
261     /**
262      * Performs atomic addition of [delta].
263      */
264     public inline operator fun plusAssign(delta: Int)
265 
266     /**
267      * Performs atomic subtraction of [delta].
268      */
269     public inline operator fun minusAssign(delta: Int)
270 }
271 
272 /**
273  * Infinite loop that reads this atomic variable and performs the specified [action] on its value.
274  */
275 public inline fun AtomicInt.loop(action: (Int) -> Unit): Nothing {
276     while (true) {
277         action(value)
278     }
279 }
280 
281 /**
282  * Updates variable atomically using the specified [function] of its value.
283  */
updatenull284 public inline fun AtomicInt.update(function: (Int) -> Int) {
285     while (true) {
286         val cur = value
287         val upd = function(cur)
288         if (compareAndSet(cur, upd)) return
289     }
290 }
291 
292 /**
293  * Updates variable atomically using the specified [function] of its value and returns its old value.
294  */
getAndUpdatenull295 public inline fun AtomicInt.getAndUpdate(function: (Int) -> Int): Int {
296     while (true) {
297         val cur = value
298         val upd = function(cur)
299         if (compareAndSet(cur, upd)) return cur
300     }
301 }
302 
303 /**
304  * Updates variable atomically using the specified [function] of its value and returns its new value.
305  */
updateAndGetnull306 public inline fun AtomicInt.updateAndGet(function: (Int) -> Int): Int {
307     while (true) {
308         val cur = value
309         val upd = function(cur)
310         if (compareAndSet(cur, upd)) return upd
311     }
312 }
313 
314 // ==================================== AtomicLong ====================================
315 
316 /**
317  * Atomic reference to a [Long] variable with volatile reads/writes via
318  * [value] property and various atomic read-modify-write operations
319  * like [compareAndSet] and others.
320  */
321 public expect class AtomicLong {
322     /**
323      * Reads/writes of this property maps to read/write of volatile variable.
324      */
325     public var value: Long
326 
327     /**
328      * Maps to [AtomicLongFieldUpdater.lazySet].
329      */
lazySetnull330     public fun lazySet(value: Long)
331 
332     /**
333      * Maps to [AtomicLongFieldUpdater.compareAndSet].
334      */
335     public fun compareAndSet(expect: Long, update: Long): Boolean
336 
337     /**
338      * Maps to [AtomicLongFieldUpdater.getAndSet].
339      */
340     public fun getAndSet(value: Long): Long
341 
342     /**
343      * Maps to [AtomicLongFieldUpdater.getAndIncrement].
344      */
345     public fun getAndIncrement(): Long
346 
347     /**
348      * Maps to [AtomicLongFieldUpdater.getAndDecrement].
349      */
350     public fun getAndDecrement(): Long
351 
352     /**
353      * Maps to [AtomicLongFieldUpdater.getAndAdd].
354      */
355     public fun getAndAdd(delta: Long): Long
356 
357     /**
358      * Maps to [AtomicLongFieldUpdater.addAndGet].
359      */
360     public fun addAndGet(delta: Long): Long
361 
362     /**
363      * Maps to [AtomicLongFieldUpdater.incrementAndGet].
364      */
365     public fun incrementAndGet(): Long
366 
367     /**
368      * Maps to [AtomicLongFieldUpdater.decrementAndGet].
369      */
370     public fun decrementAndGet(): Long
371 
372     /**
373      * Performs atomic addition of [delta].
374      */
375     public inline operator fun plusAssign(delta: Long)
376 
377     /**
378      * Performs atomic subtraction of [delta].
379      */
380     public inline operator fun minusAssign(delta: Long)
381 }
382 
383 /**
384  * Infinite loop that reads this atomic variable and performs the specified [action] on its value.
385  */
386 public inline fun AtomicLong.loop(action: (Long) -> Unit): Nothing {
387     while (true) {
388         action(value)
389     }
390 }
391 
392 /**
393  * Updates variable atomically using the specified [function] of its value.
394  */
updatenull395 public inline fun AtomicLong.update(function: (Long) -> Long) {
396     while (true) {
397         val cur = value
398         val upd = function(cur)
399         if (compareAndSet(cur, upd)) return
400     }
401 }
402 
403 /**
404  * Updates variable atomically using the specified [function] of its value and returns its old value.
405  */
getAndUpdatenull406 public inline fun AtomicLong.getAndUpdate(function: (Long) -> Long): Long {
407     while (true) {
408         val cur = value
409         val upd = function(cur)
410         if (compareAndSet(cur, upd)) return cur
411     }
412 }
413 
414 /**
415  * Updates variable atomically using the specified [function] of its value and returns its new value.
416  */
updateAndGetnull417 public inline fun AtomicLong.updateAndGet(function: (Long) -> Long): Long {
418     while (true) {
419         val cur = value
420         val upd = function(cur)
421         if (compareAndSet(cur, upd)) return upd
422     }
423 }
424 
425 // ==================================== AtomicIntArray ====================================
426 
427 /**
428  * Creates a new array of AtomicInt values of the specified size, where each element is initialised with 0
429  */
430 @JsName("AtomicIntArray\$int")
431 public class AtomicIntArray(size: Int) {
<lambda>null432     private val array = Array(size) { atomic(0) }
433 
434     @JsName("get\$atomicfu")
getnull435     public operator fun get(index: Int): AtomicInt = array[index]
436 }
437 
438 // ==================================== AtomicLongArray ====================================
439 
440 /**
441  * Creates a new array of AtomicLong values of the specified size, where each element is initialised with 0L
442  */
443 @JsName("AtomicLongArray\$long")
444 public class AtomicLongArray(size: Int) {
445     private val array = Array(size) { atomic(0L) }
446 
447     @JsName("get\$atomicfu")
448     public operator fun get(index: Int): AtomicLong = array[index]
449 }
450 
451 // ==================================== AtomicBooleanArray ====================================
452 
453 /**
454  * Creates a new array of AtomicBoolean values of the specified size, where each element is initialised with false
455  */
456 @JsName("AtomicBooleanArray\$boolean")
457 public class AtomicBooleanArray(size: Int) {
<lambda>null458     private val array = Array(size) { atomic(false) }
459 
460     @JsName("get\$atomicfu")
getnull461     public operator fun get(index: Int): AtomicBoolean = array[index]
462 }
463 
464 
465 // ==================================== AtomicArray ====================================
466 
467 @JsName("AtomicRefArray\$ref")
468 public class AtomicArray<T> internal constructor(size: Int) {
469     private val array = Array(size) { atomic<T?>(null) }
470 
471     @JsName("get\$atomicfu")
472     public operator fun get(index: Int): AtomicRef<T?> = array[index]
473 }
474