Extracted independent ThreadLocalMethods implementation to common sources
This commit is contained in:
parent
34debfcb7b
commit
67079c1565
@ -0,0 +1,90 @@
|
|||||||
|
package ru.landgrafhomyak.multitasking_0.threads
|
||||||
|
|
||||||
|
import kotlin.concurrent.atomics.ExperimentalAtomicApi
|
||||||
|
import kotlin.jvm.JvmField
|
||||||
|
import ru.landgrafhomyak.multitasking_0.SingleThreadEventLoop
|
||||||
|
import ru.landgrafhomyak.multitasking_0.fibers.Fiber
|
||||||
|
|
||||||
|
internal abstract class _CommonThreadLocalMethods(
|
||||||
|
@JvmField
|
||||||
|
protected val thread: Thread,
|
||||||
|
) : ThreadLocalMethods {
|
||||||
|
protected abstract fun _assertCurrentThread()
|
||||||
|
|
||||||
|
override fun get(): Thread {
|
||||||
|
this._assertCurrentThread()
|
||||||
|
return this.thread
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class FibersStackNode(
|
||||||
|
@JvmField
|
||||||
|
val caller: FibersStackNode?,
|
||||||
|
@JvmField
|
||||||
|
val fiber: Fiber,
|
||||||
|
) : ExitFiberCallback {
|
||||||
|
private var _isUsed = false
|
||||||
|
override val callerFiber: Fiber?
|
||||||
|
get() {
|
||||||
|
if (this._isUsed) throw IllegalStateException("Fiber already exited and value in this property isn't actual")
|
||||||
|
return this.caller?.fiber
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun exitFiber() {
|
||||||
|
this@_CommonThreadLocalMethods._assertCurrentThread()
|
||||||
|
if (this._isUsed)
|
||||||
|
throw IllegalStateException("Fiber already exited")
|
||||||
|
|
||||||
|
if (this@_CommonThreadLocalMethods._fibersStack !== this)
|
||||||
|
throw IllegalStateException("Fiber being exited isn't on top of fibers stack")
|
||||||
|
|
||||||
|
this._isUsed = true
|
||||||
|
this@_CommonThreadLocalMethods._fibersStack = this.caller
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var _fibersStack: FibersStackNode? = null
|
||||||
|
|
||||||
|
override val runningFiber: Fiber?
|
||||||
|
get() {
|
||||||
|
this._assertCurrentThread()
|
||||||
|
return this._fibersStack?.fiber
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun enterFiber(fiberToEnter: Fiber): ExitFiberCallback {
|
||||||
|
this._assertCurrentThread()
|
||||||
|
val node = this.FibersStackNode(this._fibersStack, fiberToEnter)
|
||||||
|
this._fibersStack = node
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
|
||||||
|
private var _runningEventLoop: SingleThreadEventLoop? = null
|
||||||
|
|
||||||
|
override val runningEventLoop: SingleThreadEventLoop?
|
||||||
|
get() {
|
||||||
|
this._assertCurrentThread()
|
||||||
|
return this._runningEventLoop
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@OptIn(ExperimentalAtomicApi::class)
|
||||||
|
private inner class ClearEventLoopCallbackImpl: ClearEventLoopCallback {
|
||||||
|
private var _isUsed = false
|
||||||
|
|
||||||
|
override fun clearEventLoop() {
|
||||||
|
this@_CommonThreadLocalMethods._assertCurrentThread()
|
||||||
|
if (this._isUsed)
|
||||||
|
throw IllegalStateException("Event loop already cleared")
|
||||||
|
|
||||||
|
this._isUsed = true
|
||||||
|
this@_CommonThreadLocalMethods._runningEventLoop = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setEventLoop(eventLoop: SingleThreadEventLoop): ClearEventLoopCallback {
|
||||||
|
this._assertCurrentThread()
|
||||||
|
if (this._runningEventLoop != null)
|
||||||
|
throw IllegalStateException("There is already a running event loop here")
|
||||||
|
this._runningEventLoop = eventLoop
|
||||||
|
return this.ClearEventLoopCallbackImpl()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,17 +3,15 @@ package ru.landgrafhomyak.multitasking_0.threads
|
|||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
import java.util.concurrent.locks.LockSupport
|
import java.util.concurrent.locks.LockSupport
|
||||||
import java.lang.Thread as jThread
|
import java.lang.Thread as jThread
|
||||||
import ru.landgrafhomyak.multitasking_0.fibers.Fiber
|
|
||||||
import ru.landgrafhomyak.multitasking_0.SingleThreadEventLoop
|
|
||||||
import ru.landgrafhomyak.multitasking_0.WrongCallerThreadException
|
import ru.landgrafhomyak.multitasking_0.WrongCallerThreadException
|
||||||
import ru.landgrafhomyak.multitasking_0.threads.sync.ResumeThreadCallback
|
import ru.landgrafhomyak.multitasking_0.threads.sync.ResumeThreadCallback
|
||||||
|
|
||||||
@Suppress("AMBIGUOUS_EXPECTS", "ACTUAL_WITHOUT_EXPECT")
|
@Suppress("AMBIGUOUS_EXPECTS", "ACTUAL_WITHOUT_EXPECT")
|
||||||
public actual class Thread(
|
public actual class Thread(
|
||||||
@JvmField
|
@JvmField
|
||||||
internal val _nativeThread: jThread
|
internal val _nativeThread: jThread,
|
||||||
) {
|
) {
|
||||||
private val _threadLocalMethods = this.ThreadLocalMethodsImpl()
|
private val _threadLocalMethods = ThreadLocalMethodsImpl(this)
|
||||||
|
|
||||||
actual override fun toString(): String = "<platform native thread name='${this._nativeThread.name}'>"
|
actual override fun toString(): String = "<platform native thread name='${this._nativeThread.name}'>"
|
||||||
|
|
||||||
@ -41,90 +39,14 @@ public actual class Thread(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private inner class ThreadLocalMethodsImpl : ThreadLocalMethods {
|
private class ThreadLocalMethodsImpl(thread: Thread) : _CommonThreadLocalMethods(thread), ThreadLocalMethods {
|
||||||
private fun _assertThread() {
|
override fun _assertCurrentThread() {
|
||||||
if (Thread._tl_currentThread.get() != this@Thread)
|
if (Thread._tl_currentThread.get() !== this.thread)
|
||||||
throw WrongCallerThreadException("Reference returned by 'Thread.current' must be used only in thread where it was produced")
|
throw WrongCallerThreadException("Reference returned by 'Thread.current' must be used only in thread where it was produced")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun get(): Thread {
|
|
||||||
this._assertThread()
|
|
||||||
return this@Thread
|
|
||||||
}
|
|
||||||
|
|
||||||
private inner class FibersStackNode(
|
|
||||||
@JvmField
|
|
||||||
val caller: FibersStackNode?,
|
|
||||||
@JvmField
|
|
||||||
val fiber: Fiber,
|
|
||||||
) : ExitFiberCallback {
|
|
||||||
private val _isClosed = AtomicBoolean(false)
|
|
||||||
override val callerFiber: Fiber?
|
|
||||||
get() {
|
|
||||||
if (this._isClosed.get()) throw IllegalStateException("Fiber already exited and value in this property isn't actual")
|
|
||||||
return this.caller?.fiber
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun exitFiber() {
|
|
||||||
if (this._isClosed.compareAndExchange(false, true))
|
|
||||||
throw IllegalStateException("Fiber already exited")
|
|
||||||
|
|
||||||
if (this@ThreadLocalMethodsImpl._fibersStack !== this) {
|
|
||||||
this._isClosed.set(false)
|
|
||||||
throw IllegalStateException("Fiber being exited isn't on top of fibers stack")
|
|
||||||
}
|
|
||||||
|
|
||||||
this@ThreadLocalMethodsImpl._fibersStack = this.caller
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private var _fibersStack: FibersStackNode? = null
|
|
||||||
|
|
||||||
override val runningFiber: Fiber?
|
|
||||||
get() {
|
|
||||||
this._assertThread()
|
|
||||||
return this._fibersStack?.fiber
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun enterFiber(fiberToEnter: Fiber): ExitFiberCallback {
|
|
||||||
this._assertThread()
|
|
||||||
val node = this.FibersStackNode(this._fibersStack, fiberToEnter)
|
|
||||||
this._fibersStack = node
|
|
||||||
return node
|
|
||||||
}
|
|
||||||
|
|
||||||
private var _runningEventLoop: SingleThreadEventLoop? = null
|
|
||||||
|
|
||||||
override val runningEventLoop: SingleThreadEventLoop?
|
|
||||||
get() {
|
|
||||||
this._assertThread()
|
|
||||||
return this._runningEventLoop
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private inner class ClearEventLoopCallbackImpl(
|
|
||||||
|
|
||||||
) : ClearEventLoopCallback {
|
|
||||||
private val _isClosed = AtomicBoolean(false)
|
|
||||||
|
|
||||||
override fun clearEventLoop() {
|
|
||||||
if (this._isClosed.compareAndExchange(false, true))
|
|
||||||
throw IllegalStateException("Event loop already cleared")
|
|
||||||
|
|
||||||
this@ThreadLocalMethodsImpl._runningEventLoop = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setEventLoop(eventLoop: SingleThreadEventLoop): ClearEventLoopCallback {
|
|
||||||
this._assertThread()
|
|
||||||
if (this._runningEventLoop != null)
|
|
||||||
throw IllegalStateException("There is already a running event loop here")
|
|
||||||
this._runningEventLoop = eventLoop
|
|
||||||
return this.ClearEventLoopCallbackImpl()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun yield() {
|
override fun yield() {
|
||||||
this._assertThread()
|
this._assertCurrentThread()
|
||||||
jThread.yield()
|
jThread.yield()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,9 +62,9 @@ public actual class Thread(
|
|||||||
this.sync.set(false)
|
this.sync.set(false)
|
||||||
throw IllegalStateException("Thread already resumed by this callback instance")
|
throw IllegalStateException("Thread already resumed by this callback instance")
|
||||||
}
|
}
|
||||||
when (this@Thread._nativeThread.state) {
|
when (this@ThreadLocalMethodsImpl.thread._nativeThread.state) {
|
||||||
jThread.State.WAITING, jThread.State.TIMED_WAITING -> {
|
jThread.State.WAITING, jThread.State.TIMED_WAITING -> {
|
||||||
LockSupport.unpark(this@Thread._nativeThread)
|
LockSupport.unpark(this@ThreadLocalMethodsImpl.thread._nativeThread)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
@ -155,7 +77,7 @@ public actual class Thread(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun suspendThread(store: (ResumeThreadCallback) -> Unit) {
|
override fun suspendThread(store: (ResumeThreadCallback) -> Unit) {
|
||||||
this._assertThread()
|
this._assertCurrentThread()
|
||||||
val resumer = this.ResumeThreadCallbackImpl()
|
val resumer = this.ResumeThreadCallbackImpl()
|
||||||
store(resumer)
|
store(resumer)
|
||||||
run {
|
run {
|
||||||
@ -180,7 +102,7 @@ public actual class Thread(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun suspendThread(timeoutMillis: UInt, timeoutHandler: ResumeThreadCallback.TimeoutHandler, store: (ResumeThreadCallback) -> Unit) {
|
override fun suspendThread(timeoutMillis: UInt, timeoutHandler: ResumeThreadCallback.TimeoutHandler, store: (ResumeThreadCallback) -> Unit) {
|
||||||
this._assertThread()
|
this._assertCurrentThread()
|
||||||
val resumer = this.ResumeThreadCallbackImpl()
|
val resumer = this.ResumeThreadCallbackImpl()
|
||||||
store(resumer)
|
store(resumer)
|
||||||
run {
|
run {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user