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