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("NOTHING_TO_INLINE", "RedundantVisibilityModifier", "CanBePrimaryConstructorProperty")
6
7 package kotlinx.atomicfu
8
9 import kotlin.native.concurrent.AtomicInt as KAtomicInt
10 import kotlin.native.concurrent.AtomicLong as KAtomicLong
11 import kotlin.native.concurrent.FreezableAtomicReference as KAtomicRef
12 import kotlin.native.concurrent.isFrozen
13 import kotlin.native.concurrent.freeze
14
atomicnull15 public actual fun <T> atomic(initial: T): AtomicRef<T> = AtomicRef<T>(KAtomicRef(initial))
16 public actual fun atomic(initial: Int): AtomicInt = AtomicInt(KAtomicInt(initial))
17 public actual fun atomic(initial: Long): AtomicLong = AtomicLong(KAtomicLong(initial))
18 public actual fun atomic(initial: Boolean): AtomicBoolean = AtomicBoolean(KAtomicInt(if (initial) 1 else 0))
19
20 // ==================================== AtomicRef ====================================
21
22 @Suppress("ACTUAL_WITHOUT_EXPECT", "EXPERIMENTAL_FEATURE_WARNING", "NON_PUBLIC_PRIMARY_CONSTRUCTOR_OF_INLINE_CLASS")
23 public actual inline class AtomicRef<T> internal constructor(@PublishedApi internal val a: KAtomicRef<T>) {
24 public actual inline var value: T
25 get() = a.value
26 set(value) {
27 if (a.isFrozen) value.freeze()
28 a.value = value
29 }
30
31 public actual inline fun lazySet(value: T) {
32 if (a.isFrozen) value.freeze()
33 a.value = value
34 }
35
36 public actual inline fun compareAndSet(expect: T, update: T): Boolean {
37 if (a.isFrozen) update.freeze()
38 return a.compareAndSet(expect, update)
39 }
40
41 public actual fun getAndSet(value: T): T {
42 if (a.isFrozen) value.freeze()
43 while (true) {
44 val cur = a.value
45 if (cur === value) return cur
46 if (a.compareAndSwap(cur, value) === cur) return cur
47 }
48 }
49
50 override fun toString(): String = value.toString()
51 }
52
53 // ==================================== AtomicBoolean ====================================
54
55 @Suppress("ACTUAL_WITHOUT_EXPECT", "EXPERIMENTAL_FEATURE_WARNING", "NON_PUBLIC_PRIMARY_CONSTRUCTOR_OF_INLINE_CLASS")
56 public actual inline class AtomicBoolean internal constructor(@PublishedApi internal val a: KAtomicInt) {
57 public actual inline var value: Boolean
58 get() = a.value != 0
59 set(value) { a.value = if (value) 1 else 0 }
60
lazySetnull61 public actual inline fun lazySet(value: Boolean) { this.value = value }
62
compareAndSetnull63 public actual fun compareAndSet(expect: Boolean, update: Boolean): Boolean {
64 val iExpect = if (expect) 1 else 0
65 val iUpdate = if (update) 1 else 0
66 return a.compareAndSet(iExpect, iUpdate)
67 }
68
getAndSetnull69 public actual fun getAndSet(value: Boolean): Boolean {
70 val iValue = if (value) 1 else 0
71 while (true) {
72 val cur = a.value
73 if (cur == iValue) return value
74 if (a.compareAndSet(cur, iValue)) return cur != 0
75 }
76 }
77
toStringnull78 override fun toString(): String = value.toString()
79 }
80
81 // ==================================== AtomicInt ====================================
82
83 @Suppress("ACTUAL_WITHOUT_EXPECT", "EXPERIMENTAL_FEATURE_WARNING", "NON_PUBLIC_PRIMARY_CONSTRUCTOR_OF_INLINE_CLASS")
84 public actual inline class AtomicInt internal constructor(@PublishedApi internal val a: KAtomicInt) {
85 public actual inline var value: Int
86 get() = a.value
87 set(value) { a.value = value }
88
89 public actual inline fun lazySet(value: Int) { a.value = value }
90
91 public actual inline fun compareAndSet(expect: Int, update: Int): Boolean =
92 a.compareAndSet(expect, update)
93
94 public actual fun getAndSet(value: Int): Int {
95 while (true) {
96 val cur = a.value
97 if (cur == value) return cur
98 if (a.compareAndSet(cur, value)) return cur
99 }
100 }
101
102 public actual inline fun getAndIncrement(): Int = a.addAndGet(1) - 1
103 public actual inline fun getAndDecrement(): Int = a.addAndGet(-1) + 1
104 public actual inline fun getAndAdd(delta: Int): Int = a.addAndGet(delta) - delta
105 public actual inline fun addAndGet(delta: Int): Int = a.addAndGet(delta)
106 public actual inline fun incrementAndGet(): Int = a.addAndGet(1)
107 public actual inline fun decrementAndGet(): Int = a.addAndGet(-1)
108
109 public actual inline operator fun plusAssign(delta: Int) { getAndAdd(delta) }
110 public actual inline operator fun minusAssign(delta: Int) { getAndAdd(-delta) }
111
112 override fun toString(): String = value.toString()
113 }
114
115 // ==================================== AtomicLong ====================================
116
117 @Suppress("ACTUAL_WITHOUT_EXPECT", "EXPERIMENTAL_FEATURE_WARNING", "NON_PUBLIC_PRIMARY_CONSTRUCTOR_OF_INLINE_CLASS")
118 public actual inline class AtomicLong internal constructor(@PublishedApi internal val a: KAtomicLong) {
119 public actual inline var value: Long
120 get() = a.value
121 set(value) { a.value = value }
122
lazySetnull123 public actual inline fun lazySet(value: Long) { a.value = value }
124
compareAndSetnull125 public actual inline fun compareAndSet(expect: Long, update: Long): Boolean =
126 a.compareAndSet(expect, update)
127
128 public actual fun getAndSet(value: Long): Long {
129 while (true) {
130 val cur = a.value
131 if (cur == value) return cur
132 if (a.compareAndSet(cur, value)) return cur
133 }
134 }
135
getAndIncrementnull136 public actual inline fun getAndIncrement(): Long = a.addAndGet(1) - 1
137 public actual inline fun getAndDecrement(): Long = a.addAndGet(-1) + 1
138 public actual inline fun getAndAdd(delta: Long): Long = a.addAndGet(delta) - delta
139 public actual inline fun addAndGet(delta: Long): Long = a.addAndGet(delta)
140 public actual inline fun incrementAndGet(): Long = a.addAndGet(1)
141 public actual inline fun decrementAndGet(): Long = a.addAndGet(-1)
142
143 public actual inline operator fun plusAssign(delta: Long) { getAndAdd(delta) }
minusAssignnull144 public actual inline operator fun minusAssign(delta: Long) { getAndAdd(-delta) }
145
toStringnull146 override fun toString(): String = value.toString()
147 }
148
149