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(
6 "NOTHING_TO_INLINE",
7 "RedundantVisibilityModifier",
8 "CanBePrimaryConstructorProperty",
9 "INVISIBLE_REFERENCE",
10 "INVISIBLE_MEMBER"
11 )
12
13 package kotlinx.atomicfu
14
15 import kotlin.concurrent.AtomicInt as KAtomicInt
16 import kotlin.concurrent.AtomicLong as KAtomicLong
17 import kotlin.concurrent.AtomicReference as KAtomicRef
18 import kotlin.native.concurrent.isFrozen
19 import kotlin.native.concurrent.freeze
20 import kotlin.reflect.KProperty
21 import kotlinx.atomicfu.TraceBase.None
22 import kotlin.internal.InlineOnly
23
atomicnull24 public actual fun <T> atomic(initial: T, trace: TraceBase): AtomicRef<T> = AtomicRef<T>(KAtomicRef(initial))
25 public actual fun <T> atomic(initial: T): AtomicRef<T> = atomic(initial, None)
26 public actual fun atomic(initial: Int, trace: TraceBase): AtomicInt = AtomicInt(KAtomicInt(initial))
27 public actual fun atomic(initial: Int): AtomicInt = atomic(initial, None)
28 public actual fun atomic(initial: Long, trace: TraceBase): AtomicLong = AtomicLong(KAtomicLong(initial))
29 public actual fun atomic(initial: Long): AtomicLong = atomic(initial, None)
30 public actual fun atomic(initial: Boolean, trace: TraceBase): AtomicBoolean = AtomicBoolean(KAtomicInt(if (initial) 1 else 0))
31 public actual fun atomic(initial: Boolean): AtomicBoolean = atomic(initial, None)
32
33 // ==================================== AtomicRef ====================================
34
35 @Suppress("ACTUAL_WITHOUT_EXPECT")
36 public actual class AtomicRef<T> internal constructor(@PublishedApi internal val a: KAtomicRef<T>) {
37 public actual inline var value: T
38 get() = a.value
39 set(value) {
40 if (a.isFrozen) value.freeze()
41 a.value = value
42 }
43
44 @InlineOnly
45 public actual inline operator fun getValue(thisRef: Any?, property: KProperty<*>): T = value
46
47 @InlineOnly
48 public actual inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { this.value = value }
49
50 public actual inline fun lazySet(value: T) {
51 if (a.isFrozen) value.freeze()
52 a.value = value
53 }
54
55 public actual inline fun compareAndSet(expect: T, update: T): Boolean {
56 if (a.isFrozen) update.freeze()
57 return a.compareAndSet(expect, update)
58 }
59
60 public actual fun getAndSet(value: T): T {
61 if (a.isFrozen) value.freeze()
62 while (true) {
63 val cur = a.value
64 if (cur === value) return cur
65 if (a.compareAndExchange(cur, value) === cur) return cur
66 }
67 }
68
69 override fun toString(): String = value.toString()
70 }
71
72 // ==================================== AtomicBoolean ====================================
73
74 @Suppress("ACTUAL_WITHOUT_EXPECT")
75 public actual class AtomicBoolean internal constructor(@PublishedApi internal val a: KAtomicInt) {
76 public actual inline var value: Boolean
77 get() = a.value != 0
78 set(value) { a.value = if (value) 1 else 0 }
79
getValuenull80 public actual inline operator fun getValue(thisRef: Any?, property: KProperty<*>): Boolean = value
81
82 public actual inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean) { this.value = value }
83
lazySetnull84 public actual inline fun lazySet(value: Boolean) { this.value = value }
85
compareAndSetnull86 public actual fun compareAndSet(expect: Boolean, update: Boolean): Boolean {
87 val iExpect = if (expect) 1 else 0
88 val iUpdate = if (update) 1 else 0
89 return a.compareAndSet(iExpect, iUpdate)
90 }
91
getAndSetnull92 public actual fun getAndSet(value: Boolean): Boolean {
93 val iValue = if (value) 1 else 0
94 while (true) {
95 val cur = a.value
96 if (cur == iValue) return value
97 if (a.compareAndSet(cur, iValue)) return cur != 0
98 }
99 }
100
toStringnull101 override fun toString(): String = value.toString()
102 }
103
104 // ==================================== AtomicInt ====================================
105
106 @Suppress("ACTUAL_WITHOUT_EXPECT")
107 public actual class AtomicInt internal constructor(@PublishedApi internal val a: KAtomicInt) {
108 public actual inline var value: Int
109 get() = a.value
110 set(value) { a.value = value }
111
112 @InlineOnly
113 actual inline operator fun getValue(thisRef: Any?, property: KProperty<*>): Int = value
114
115 @InlineOnly
116 public actual inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) { this.value = value }
117
118 public actual inline fun lazySet(value: Int) { a.value = value }
119
120 public actual inline fun compareAndSet(expect: Int, update: Int): Boolean =
121 a.compareAndSet(expect, update)
122
123 public actual fun getAndSet(value: Int): Int {
124 while (true) {
125 val cur = a.value
126 if (cur == value) return cur
127 if (a.compareAndSet(cur, value)) return cur
128 }
129 }
130
131 public actual inline fun getAndIncrement(): Int = a.addAndGet(1) - 1
132 public actual inline fun getAndDecrement(): Int = a.addAndGet(-1) + 1
133 public actual inline fun getAndAdd(delta: Int): Int = a.addAndGet(delta) - delta
134 public actual inline fun addAndGet(delta: Int): Int = a.addAndGet(delta)
135 public actual inline fun incrementAndGet(): Int = a.addAndGet(1)
136 public actual inline fun decrementAndGet(): Int = a.addAndGet(-1)
137
138 public actual inline operator fun plusAssign(delta: Int) { getAndAdd(delta) }
139 public actual inline operator fun minusAssign(delta: Int) { getAndAdd(-delta) }
140
141 override fun toString(): String = value.toString()
142 }
143
144 // ==================================== AtomicLong ====================================
145
146 @Suppress("ACTUAL_WITHOUT_EXPECT")
147 public actual class AtomicLong internal constructor(@PublishedApi internal val a: KAtomicLong) {
148 public actual inline var value: Long
149 get() = a.value
150 set(value) { a.value = value }
151
getValuenull152 public actual inline operator fun getValue(thisRef: Any?, property: KProperty<*>): Long = value
153
154 public actual inline operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Long) { this.value = value }
155
lazySetnull156 public actual inline fun lazySet(value: Long) { a.value = value }
157
compareAndSetnull158 public actual inline fun compareAndSet(expect: Long, update: Long): Boolean =
159 a.compareAndSet(expect, update)
160
161 public actual fun getAndSet(value: Long): Long {
162 while (true) {
163 val cur = a.value
164 if (cur == value) return cur
165 if (a.compareAndSet(cur, value)) return cur
166 }
167 }
168
getAndIncrementnull169 public actual inline fun getAndIncrement(): Long = a.addAndGet(1L) - 1
170 public actual inline fun getAndDecrement(): Long = a.addAndGet(-1L) + 1
171 public actual inline fun getAndAdd(delta: Long): Long = a.addAndGet(delta) - delta
172 public actual inline fun addAndGet(delta: Long): Long = a.addAndGet(delta)
173 public actual inline fun incrementAndGet(): Long = a.addAndGet(1L)
174 public actual inline fun decrementAndGet(): Long = a.addAndGet(-1L)
175
176 public actual inline operator fun plusAssign(delta: Long) { getAndAdd(delta) }
minusAssignnull177 public actual inline operator fun minusAssign(delta: Long) { getAndAdd(-delta) }
178
toStringnull179 override fun toString(): String = value.toString()
180 }
181
182