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 import kotlin.reflect.KProperty
15 import kotlinx.atomicfu.TraceBase.None
16
atomicnull17 public actual fun <T> atomic(initial: T, trace: TraceBase): AtomicRef<T> = AtomicRef<T>(KAtomicRef(initial))
18 public actual fun <T> atomic(initial: T): AtomicRef<T> = atomic(initial, None)
19 public actual fun atomic(initial: Int, trace: TraceBase): AtomicInt = AtomicInt(KAtomicInt(initial))
20 public actual fun atomic(initial: Int): AtomicInt = atomic(initial, None)
21 public actual fun atomic(initial: Long, trace: TraceBase): AtomicLong = AtomicLong(KAtomicLong(initial))
22 public actual fun atomic(initial: Long): AtomicLong = atomic(initial, None)
23 public actual fun atomic(initial: Boolean, trace: TraceBase): AtomicBoolean = AtomicBoolean(KAtomicInt(if (initial) 1 else 0))
24 public actual fun atomic(initial: Boolean): AtomicBoolean = atomic(initial, None)
25
26 // ==================================== AtomicRef ====================================
27
28 @Suppress("ACTUAL_WITHOUT_EXPECT", "EXPERIMENTAL_FEATURE_WARNING", "NON_PUBLIC_PRIMARY_CONSTRUCTOR_OF_INLINE_CLASS")
29 public actual inline class AtomicRef<T> internal constructor(@PublishedApi internal val a: KAtomicRef<T>) {
30 public actual inline var value: T
31 get() = a.value
32 set(value) {
33 if (a.isFrozen) value.freeze()
34 a.value = value
35 }
36
37 public actual inline operator fun getValue(thisRef: Any?, property: KProperty<*>): T = value
38
39 public actual inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { this.value = value }
40
41 public actual inline fun lazySet(value: T) {
42 if (a.isFrozen) value.freeze()
43 a.value = value
44 }
45
46 public actual inline fun compareAndSet(expect: T, update: T): Boolean {
47 if (a.isFrozen) update.freeze()
48 return a.compareAndSet(expect, update)
49 }
50
51 public actual fun getAndSet(value: T): T {
52 if (a.isFrozen) value.freeze()
53 while (true) {
54 val cur = a.value
55 if (cur === value) return cur
56 if (a.compareAndSwap(cur, value) === cur) return cur
57 }
58 }
59
60 override fun toString(): String = value.toString()
61 }
62
63 // ==================================== AtomicBoolean ====================================
64
65 @Suppress("ACTUAL_WITHOUT_EXPECT", "EXPERIMENTAL_FEATURE_WARNING", "NON_PUBLIC_PRIMARY_CONSTRUCTOR_OF_INLINE_CLASS")
66 public actual inline class AtomicBoolean internal constructor(@PublishedApi internal val a: KAtomicInt) {
67 public actual inline var value: Boolean
68 get() = a.value != 0
69 set(value) { a.value = if (value) 1 else 0 }
70
getValuenull71 public actual inline operator fun getValue(thisRef: Any?, property: KProperty<*>): Boolean = value
72
73 public actual inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean) { this.value = value }
74
lazySetnull75 public actual inline fun lazySet(value: Boolean) { this.value = value }
76
compareAndSetnull77 public actual fun compareAndSet(expect: Boolean, update: Boolean): Boolean {
78 val iExpect = if (expect) 1 else 0
79 val iUpdate = if (update) 1 else 0
80 return a.compareAndSet(iExpect, iUpdate)
81 }
82
getAndSetnull83 public actual fun getAndSet(value: Boolean): Boolean {
84 val iValue = if (value) 1 else 0
85 while (true) {
86 val cur = a.value
87 if (cur == iValue) return value
88 if (a.compareAndSet(cur, iValue)) return cur != 0
89 }
90 }
91
toStringnull92 override fun toString(): String = value.toString()
93 }
94
95 // ==================================== AtomicInt ====================================
96
97 @Suppress("ACTUAL_WITHOUT_EXPECT", "EXPERIMENTAL_FEATURE_WARNING", "NON_PUBLIC_PRIMARY_CONSTRUCTOR_OF_INLINE_CLASS")
98 public actual inline class AtomicInt internal constructor(@PublishedApi internal val a: KAtomicInt) {
99 public actual inline var value: Int
100 get() = a.value
101 set(value) { a.value = value }
102
103 actual inline operator fun getValue(thisRef: Any?, property: KProperty<*>): Int = value
104
105 public actual inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { this.value = value }
106
107 public actual inline fun lazySet(value: Int) { a.value = value }
108
109 public actual inline fun compareAndSet(expect: Int, update: Int): Boolean =
110 a.compareAndSet(expect, update)
111
112 public actual fun getAndSet(value: Int): Int {
113 while (true) {
114 val cur = a.value
115 if (cur == value) return cur
116 if (a.compareAndSet(cur, value)) return cur
117 }
118 }
119
120 public actual inline fun getAndIncrement(): Int = a.addAndGet(1) - 1
121 public actual inline fun getAndDecrement(): Int = a.addAndGet(-1) + 1
122 public actual inline fun getAndAdd(delta: Int): Int = a.addAndGet(delta) - delta
123 public actual inline fun addAndGet(delta: Int): Int = a.addAndGet(delta)
124 public actual inline fun incrementAndGet(): Int = a.addAndGet(1)
125 public actual inline fun decrementAndGet(): Int = a.addAndGet(-1)
126
127 public actual inline operator fun plusAssign(delta: Int) { getAndAdd(delta) }
128 public actual inline operator fun minusAssign(delta: Int) { getAndAdd(-delta) }
129
130 override fun toString(): String = value.toString()
131 }
132
133 // ==================================== AtomicLong ====================================
134
135 @Suppress("ACTUAL_WITHOUT_EXPECT", "EXPERIMENTAL_FEATURE_WARNING", "NON_PUBLIC_PRIMARY_CONSTRUCTOR_OF_INLINE_CLASS")
136 public actual inline class AtomicLong internal constructor(@PublishedApi internal val a: KAtomicLong) {
137 public actual inline var value: Long
138 get() = a.value
139 set(value) { a.value = value }
140
getValuenull141 public actual inline operator fun getValue(thisRef: Any?, property: KProperty<*>): Long = value
142
143 public actual inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Long) { this.value = value }
144
lazySetnull145 public actual inline fun lazySet(value: Long) { a.value = value }
146
compareAndSetnull147 public actual inline fun compareAndSet(expect: Long, update: Long): Boolean =
148 a.compareAndSet(expect, update)
149
150 public actual fun getAndSet(value: Long): Long {
151 while (true) {
152 val cur = a.value
153 if (cur == value) return cur
154 if (a.compareAndSet(cur, value)) return cur
155 }
156 }
157
getAndIncrementnull158 public actual inline fun getAndIncrement(): Long = a.addAndGet(1) - 1
159 public actual inline fun getAndDecrement(): Long = a.addAndGet(-1) + 1
160 public actual inline fun getAndAdd(delta: Long): Long = a.addAndGet(delta) - delta
161 public actual inline fun addAndGet(delta: Long): Long = a.addAndGet(delta)
162 public actual inline fun incrementAndGet(): Long = a.addAndGet(1)
163 public actual inline fun decrementAndGet(): Long = a.addAndGet(-1)
164
165 public actual inline operator fun plusAssign(delta: Long) { getAndAdd(delta) }
minusAssignnull166 public actual inline operator fun minusAssign(delta: Long) { getAndAdd(-delta) }
167
toStringnull168 override fun toString(): String = value.toString()
169 }
170
171