Skip to content

Commit 43a00dc

Browse files
elizarovqwwdfsad
authored andcommitted
~ Use WorkerBoundReference
1 parent 91f9468 commit 43a00dc

File tree

4 files changed

+33
-27
lines changed

4 files changed

+33
-27
lines changed

kotlinx-coroutines-core/native/src/Thread.native.kt

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ internal fun currentThread(): Thread = currentThread
1818

1919
internal expect fun initCurrentThread(): Thread
2020

21+
internal expect fun Worker.toThread(): Thread
22+
2123
internal fun Worker.execute(block: () -> Unit) {
2224
block.freeze()
2325
executeAfter(0, block)

kotlinx-coroutines-core/native/src/internal/Sharing.kt

+24-27
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
package kotlinx.coroutines.internal
66

77
import kotlinx.atomicfu.*
8-
import kotlinx.cinterop.*
98
import kotlinx.coroutines.*
109
import kotlin.coroutines.*
1110
import kotlin.coroutines.intrinsics.*
@@ -57,6 +56,7 @@ internal actual fun <T> Continuation<T>.useLocal() : Continuation<T> = when (thi
5756

5857
internal actual fun <T> Continuation<T>.shareableInterceptedResumeCancellableWith(result: Result<T>) {
5958
this as ShareableContinuation<T> // must have been shared
59+
val thread = ownerThreadOrNull ?: wasUsed()
6060
if (currentThread() == thread) {
6161
useRef().intercepted().resumeCancellableWith(result)
6262
} else {
@@ -68,6 +68,7 @@ internal actual fun <T> Continuation<T>.shareableInterceptedResumeCancellableWit
6868

6969
internal actual fun <T> Continuation<T>.shareableInterceptedResumeWith(result: Result<T>) {
7070
this as ShareableContinuation<T> // must have been shared
71+
val thread = ownerThreadOrNull ?: wasUsed()
7172
if (currentThread() == thread) {
7273
useRef().intercepted().resumeWith(result)
7374
} else {
@@ -102,10 +103,11 @@ internal actual inline fun disposeContinuation(cont: () -> Continuation<*>) {
102103

103104
internal actual fun <T> CancellableContinuationImpl<T>.shareableResume(delegate: Continuation<T>, useMode: Int) {
104105
if (delegate is ShareableContinuation) {
105-
if (currentThread() == delegate.thread) {
106+
val thread = delegate.ownerThreadOrNull ?: delegate.wasUsed()
107+
if (currentThread() == thread) {
106108
resumeImpl(delegate.useRef(), useMode)
107109
} else {
108-
delegate.thread.execute {
110+
thread.execute {
109111
resumeImpl(delegate.useRef(), useMode)
110112
}
111113
}
@@ -144,54 +146,46 @@ internal actual inline fun Any.weakRef(): Any = WeakReference(this)
144146
internal actual fun Any?.unweakRef(): Any? = (this as WeakReference<*>?)?.get()
145147

146148
internal open class ShareableObject<T : Any>(obj: T) {
147-
val thread: Thread = currentThread()
148-
149-
// todo: this is the best effort (fail-fast) double-dispose protection, does not provide memory safety guarantee
150-
private val _ref = atomic<StableRef<T>?>(StableRef.create(obj))
149+
private val _ref = atomic<WorkerBoundReference<T>?>(WorkerBoundReference(obj))
151150

151+
val ownerThreadOrNull: Thread?
152+
get() = _ref.value?.worker?.toThread()
153+
152154
fun localRef(): T {
153-
checkThread()
154155
val ref = _ref.value ?: wasUsed()
155-
return ref.get()
156+
return ref.value
156157
}
157158

158159
fun localRefOrNull(): T? {
159-
val current = currentThread()
160-
if (current != thread) return null
161160
val ref = _ref.value ?: wasUsed()
162-
return ref.get()
161+
if (Worker.current != ref.worker) return null
162+
return ref.value
163163
}
164164

165165
fun localRefOrNullIfNotUsed(): T? {
166-
val current = currentThread()
167-
if (current != thread) return null
168166
val ref = _ref.value ?: return null
169-
return ref.get()
167+
if (Worker.current != ref.worker) return null
168+
return ref.value
170169
}
171170

172171
fun useRef(): T {
173-
checkThread()
174172
val ref = _ref.getAndSet(null) ?: wasUsed()
175-
return ref.get().also { ref.dispose() }
173+
return ref.value
176174
}
177175

178176
fun disposeRef(): T? {
179-
checkThread()
180177
val ref = _ref.getAndSet(null) ?: return null
181-
return ref.get().also { ref.dispose() }
178+
return ref.value
182179
}
183180

184-
private fun checkThread() {
185-
val current = currentThread()
186-
if (current != thread) error("Ref $classSimpleName@$hexAddress can be used only from thread $thread but now in $current")
187-
}
188-
189-
private fun wasUsed(): Nothing {
181+
fun wasUsed(): Nothing {
190182
error("Ref $classSimpleName@$hexAddress was already used")
191183
}
192184

193-
override fun toString(): String =
194-
"Shareable[${if (currentThread() == thread) _ref.value?.get()?.toString() ?: "used" else "wrong thread"}]"
185+
override fun toString(): String {
186+
val ref = _ref.value ?: return "Shareable[used]"
187+
return "Shareable[${if (Worker.current == ref.worker) _ref.value.toString() else "wrong worker"}]"
188+
}
195189
}
196190

197191
@PublishedApi
@@ -201,6 +195,7 @@ internal class ShareableContinuation<T>(
201195
override val context: CoroutineContext = cont.context
202196

203197
override fun resumeWith(result: Result<T>) {
198+
val thread = ownerThreadOrNull ?: wasUsed()
204199
if (currentThread() == thread) {
205200
useRef().resumeWith(result)
206201
} else {
@@ -215,6 +210,7 @@ private class ShareableDisposableHandle(
215210
handle: DisposableHandle
216211
) : ShareableObject<DisposableHandle>(handle), DisposableHandle {
217212
override fun dispose() {
213+
val thread = ownerThreadOrNull ?: return
218214
if (currentThread() == thread) {
219215
disposeRef()?.dispose()
220216
} else {
@@ -247,6 +243,7 @@ private class ShareableBlock<T, R>(
247243

248244
fun dispose(useIt: Boolean) {
249245
if (willBeUsed.value && !useIt) return
246+
val thread = ownerThreadOrNull ?: return
250247
if (currentThread() == thread) {
251248
disposeRef()
252249
} else {

kotlinx-coroutines-core/nativeDarwin/src/Thread.kt

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ public fun initMainThread() {
2222
internal actual fun initCurrentThread(): Thread =
2323
if (isMainThread()) mainThread else WorkerThread()
2424

25+
internal actual fun Worker.toThread(): Thread =
26+
if (this == mainThread.worker) mainThread else WorkerThread(this)
27+
2528
@SharedImmutable
2629
private val _mainThread = AtomicReference<MainThread?>(null)
2730

kotlinx-coroutines-core/nativeOther/src/Thread.kt

+4
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,8 @@
44

55
package kotlinx.coroutines
66

7+
import kotlin.native.concurrent.*
8+
79
internal actual fun initCurrentThread(): Thread = WorkerThread()
10+
11+
internal actual fun Worker.toThread(): Thread = WorkerThread(this)

0 commit comments

Comments
 (0)