Docs for thread and minor fixes and improvements
This commit is contained in:
parent
8fab4c9e57
commit
85e693aba8
@ -0,0 +1,10 @@
|
|||||||
|
package ru.landgrafhomyak.multitasking_0
|
||||||
|
|
||||||
|
import kotlin.RuntimeException
|
||||||
|
|
||||||
|
public class WrongCallerThreadException : RuntimeException {
|
||||||
|
public constructor() : super()
|
||||||
|
public constructor(message: String?) : super(message)
|
||||||
|
public constructor(message: String?, cause: Throwable?) : super(message, cause)
|
||||||
|
public constructor(cause: Throwable?) : super(cause)
|
||||||
|
}
|
||||||
@ -3,12 +3,24 @@ package ru.landgrafhomyak.multitasking_0.threads
|
|||||||
import ru.landgrafhomyak.multitasking_0.Fiber
|
import ru.landgrafhomyak.multitasking_0.Fiber
|
||||||
|
|
||||||
public expect class Thread {
|
public expect class Thread {
|
||||||
|
/**
|
||||||
|
* Name of thread for debug purposes.
|
||||||
|
*/
|
||||||
public val name: String
|
public val name: String
|
||||||
override fun toString(): String
|
override fun toString(): String
|
||||||
|
|
||||||
public var runningFiber: Fiber?
|
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
public fun currentThread(): Thread
|
/**
|
||||||
|
* Thread-local getter that returns object with access to some thread-local meta-information.
|
||||||
|
*
|
||||||
|
* Passing this object to another thread is not allowed and his members will throw error.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* ***Java's [virtual threads](https://docs.oracle.com/en/java/javase/21/core/virtual-threads.html) note:***
|
||||||
|
* If called inside [virtual thread used as fiber][ru.landgrafhomyak.multitasking_0.threads.impl.java_virtual_threads.JavaVirtualThreadFiber],
|
||||||
|
* it will return object associated with [Fiber.resumedOnThread] instead of actual thread.
|
||||||
|
* If a virtual thread is created another way, it will return its own descriptor.
|
||||||
|
*/
|
||||||
|
public val current: ThreadLocalMethods
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,58 @@
|
|||||||
|
package ru.landgrafhomyak.multitasking_0.threads
|
||||||
|
|
||||||
|
import ru.landgrafhomyak.multitasking_0.Fiber
|
||||||
|
import ru.landgrafhomyak.multitasking_0.SingleThreadEventLoop
|
||||||
|
import ru.landgrafhomyak.multitasking_0.WrongCallerThreadException
|
||||||
|
|
||||||
|
public expect sealed interface ThreadLocalMethods {
|
||||||
|
/**
|
||||||
|
* Returns descriptor of current thread.
|
||||||
|
*
|
||||||
|
* @throws WrongCallerThreadException if called on thread different that caller of [Thread.current].
|
||||||
|
*/
|
||||||
|
public fun get(): Thread
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns descriptor of [fiber][Fiber] that is currently [running (or emulates running)][Fiber.resume]
|
||||||
|
* in this thread.
|
||||||
|
*
|
||||||
|
* If set, condition `Thread.current.runningFiber.resumedOnThread === Thread.current.get()` always true
|
||||||
|
*
|
||||||
|
* [Fiber][Fiber] implementations must control this property explicitly with [enterFiber()][ThreadLocalMethods.enterFiber]
|
||||||
|
* and [exitFiber()][ThreadLocalMethods.exitFiber]
|
||||||
|
*
|
||||||
|
* @throws WrongCallerThreadException if called on thread different that caller of [Thread.current].
|
||||||
|
*/
|
||||||
|
public val runningFiber: Fiber?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Informs thread that execution flow was switched to [fiber][Fiber].
|
||||||
|
*
|
||||||
|
* @param fiberToEnter descriptor of fiber that is [going to run][Fiber.resume].
|
||||||
|
* @param privateToken secret reference that should be used to call [exitFiber()][ThreadLocalMethods.exitFiber].
|
||||||
|
* Need to avoid clearing [information about running fiber][ThreadLocalMethods.runningFiber]
|
||||||
|
* by anyone except implementation of this fiber.
|
||||||
|
* @return [fiber][Fiber] in which this function was called or `null` if it was called in thread.
|
||||||
|
*
|
||||||
|
* @throws WrongCallerThreadException if called on thread different that caller of [Thread.current].
|
||||||
|
*/
|
||||||
|
public fun enterFiber(fiberToEnter: Fiber, privateToken: Any): Fiber?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Informs thread that execution flow was returned from [fiber][Fiber].
|
||||||
|
*
|
||||||
|
* @param fiberToExit descriptor of fiber that is [going to return execution flow][Fiber.yield].
|
||||||
|
* @param privateToken secret reference that was passed to [enterFiber()][ThreadLocalMethods.exitFiber].
|
||||||
|
* Used to check that this function called by same caller as [enterFiber()][ThreadLocalMethods.exitFiber].
|
||||||
|
* @param fiberToRestore return value of corresponding [enterFiber()][ThreadLocalMethods.exitFiber] call.
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException if [fiberToExit] or [fiberToRestore] doesn't match.
|
||||||
|
* @throws IllegalArgumentException if [privateToken] doesn't match.
|
||||||
|
* @throws WrongCallerThreadException if called on thread different that caller of [Thread.current].
|
||||||
|
*/
|
||||||
|
public fun exitFiber(fiberToExit: Fiber, privateToken: Any, fiberToRestore: Fiber?)
|
||||||
|
|
||||||
|
public val runningEventLoop: SingleThreadEventLoop?
|
||||||
|
public fun setEventLoop(eventLoop: SingleThreadEventLoop, privateToken: Any)
|
||||||
|
public fun clearEventLoop(eventLoop: SingleThreadEventLoop, privateToken: Any)
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
package ru.landgrafhomyak.multitasking_0.threads
|
||||||
|
|
||||||
|
import kotlin.jvm.JvmField
|
||||||
|
import ru.landgrafhomyak.multitasking_0.Fiber
|
||||||
|
|
||||||
|
internal class _FibersStackNode(
|
||||||
|
@JvmField
|
||||||
|
val caller: _FibersStackNode?,
|
||||||
|
@JvmField
|
||||||
|
val fiber: Fiber,
|
||||||
|
@JvmField
|
||||||
|
val privateToken: Any,
|
||||||
|
) {
|
||||||
|
fun assertExit(fiberToExit: Fiber, privateToken: Any, fiberToRestore: Fiber?) {
|
||||||
|
if (this.fiber !== fiberToExit || this.caller?.fiber !== fiberToRestore)
|
||||||
|
throw IllegalStateException("fiberToExit or fiberToRestore doesn't match")
|
||||||
|
|
||||||
|
if (this.privateToken !== privateToken)
|
||||||
|
throw IllegalArgumentException("privateToken doesn't match")
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,12 +2,11 @@ package ru.landgrafhomyak.multitasking_0.threads
|
|||||||
|
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
import java.lang.Thread as jThread
|
import java.lang.Thread as jThread
|
||||||
import java.util.concurrent.locks.ReentrantLock
|
|
||||||
import kotlin.concurrent.withLock
|
import kotlin.concurrent.withLock
|
||||||
|
|
||||||
@Suppress("JoinDeclarationAndAssignment")
|
@Suppress("JoinDeclarationAndAssignment")
|
||||||
internal class DrivenPlatformThread : Thread {
|
internal class DrivenPlatformThread : Thread {
|
||||||
override fun toString(): String = TODO()
|
override fun toString(): String = "<native platform thread (externally created) name='${this.name}'${if (this._nativeThread.isVirtual) " (virtual)" else ""}>"
|
||||||
|
|
||||||
override val _nativeThread: jThread
|
override val _nativeThread: jThread
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import java.lang.Thread as jThread
|
|||||||
import kotlin.concurrent.withLock
|
import kotlin.concurrent.withLock
|
||||||
|
|
||||||
internal class ExternalThread : Thread {
|
internal class ExternalThread : Thread {
|
||||||
override fun toString(): String = TODO()
|
override fun toString(): String = "<native platform thread name='${this.name}'>"
|
||||||
|
|
||||||
override val _nativeThread: jThread
|
override val _nativeThread: jThread
|
||||||
|
|
||||||
|
|||||||
@ -4,24 +4,38 @@ import java.util.concurrent.locks.ReentrantLock
|
|||||||
import kotlin.concurrent.withLock
|
import kotlin.concurrent.withLock
|
||||||
import java.lang.Thread as jThread
|
import java.lang.Thread as jThread
|
||||||
import ru.landgrafhomyak.multitasking_0.Fiber
|
import ru.landgrafhomyak.multitasking_0.Fiber
|
||||||
|
import ru.landgrafhomyak.multitasking_0.SingleThreadEventLoop
|
||||||
|
import ru.landgrafhomyak.multitasking_0.WrongCallerThreadException
|
||||||
|
|
||||||
@Suppress("AMBIGUOUS_EXPECTS", "ACTUAL_WITHOUT_EXPECT")
|
@Suppress("AMBIGUOUS_EXPECTS", "ACTUAL_WITHOUT_EXPECT")
|
||||||
public actual sealed class Thread {
|
public actual sealed class Thread {
|
||||||
public actual var runningFiber: Fiber? = null
|
private val _threadLocalMethods = this.ThreadLocalMethodsImpl()
|
||||||
|
|
||||||
protected abstract val _nativeThread: jThread
|
protected abstract val _nativeThread: jThread
|
||||||
protected val _sync: ReentrantLock = ReentrantLock()
|
protected val _sync: ReentrantLock = ReentrantLock()
|
||||||
protected var _isExplicitlyDestroyed: Boolean = false
|
protected var _isExplicitlyDestroyed: Boolean = false
|
||||||
protected var _uncaughtException: Throwable? = null
|
protected var _uncaughtException: Throwable? = null
|
||||||
|
|
||||||
|
|
||||||
actual abstract override fun toString(): String
|
actual abstract override fun toString(): String
|
||||||
|
|
||||||
public actual val name: String
|
public actual val name: String
|
||||||
get() = this._nativeThread.name
|
get() {
|
||||||
|
this._sync.withLock {
|
||||||
|
if (this._isExplicitlyDestroyed)
|
||||||
|
throw IllegalStateException("Thread destroyed")
|
||||||
|
}
|
||||||
|
return this._nativeThread.name
|
||||||
|
}
|
||||||
|
|
||||||
public actual val isDaemon: Boolean
|
public actual val isDaemon: Boolean
|
||||||
get() = this._nativeThread.isDaemon
|
get() {
|
||||||
|
this._sync.withLock {
|
||||||
|
if (this._isExplicitlyDestroyed)
|
||||||
|
throw IllegalStateException("Thread destroyed")
|
||||||
|
}
|
||||||
|
return this._nativeThread.isDaemon
|
||||||
|
}
|
||||||
public actual val state: State
|
public actual val state: State
|
||||||
get() {
|
get() {
|
||||||
this._sync.withLock {
|
this._sync.withLock {
|
||||||
@ -30,10 +44,10 @@ public actual sealed class Thread {
|
|||||||
|
|
||||||
when (this._nativeThread.state) {
|
when (this._nativeThread.state) {
|
||||||
jThread.State.NEW -> return State.NEW
|
jThread.State.NEW -> return State.NEW
|
||||||
jThread.State.RUNNABLE -> return State.NOT_FINISHED
|
jThread.State.RUNNABLE -> return State.STARTED
|
||||||
jThread.State.BLOCKED -> return State.NOT_FINISHED
|
jThread.State.BLOCKED -> return State.STARTED
|
||||||
jThread.State.WAITING -> return State.NOT_FINISHED
|
jThread.State.WAITING -> return State.STARTED
|
||||||
jThread.State.TIMED_WAITING -> return State.NOT_FINISHED
|
jThread.State.TIMED_WAITING -> return State.STARTED
|
||||||
jThread.State.TERMINATED -> {
|
jThread.State.TERMINATED -> {
|
||||||
if (this._uncaughtException == null)
|
if (this._uncaughtException == null)
|
||||||
return State.FINISHED_SUCCESSFULLY
|
return State.FINISHED_SUCCESSFULLY
|
||||||
@ -47,6 +61,9 @@ public actual sealed class Thread {
|
|||||||
public actual val uncaughtException: Throwable
|
public actual val uncaughtException: Throwable
|
||||||
get() {
|
get() {
|
||||||
this._sync.withLock {
|
this._sync.withLock {
|
||||||
|
if (this._isExplicitlyDestroyed)
|
||||||
|
throw IllegalStateException("Thread destroyed")
|
||||||
|
|
||||||
val e = this._uncaughtException
|
val e = this._uncaughtException
|
||||||
if (e != null)
|
if (e != null)
|
||||||
return e
|
return e
|
||||||
@ -105,7 +122,7 @@ public actual sealed class Thread {
|
|||||||
|
|
||||||
public actual enum class State {
|
public actual enum class State {
|
||||||
NEW,
|
NEW,
|
||||||
NOT_FINISHED,
|
STARTED,
|
||||||
FINISHED_SUCCESSFULLY,
|
FINISHED_SUCCESSFULLY,
|
||||||
FINISHED_WITH_ERROR,
|
FINISHED_WITH_ERROR,
|
||||||
DESTROYED
|
DESTROYED
|
||||||
@ -122,11 +139,80 @@ public actual sealed class Thread {
|
|||||||
internal val _tl_currentThread: ThreadLocal<Thread?> get() = CurrentThreadVariable
|
internal val _tl_currentThread: ThreadLocal<Thread?> get() = CurrentThreadVariable
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
public actual fun create(name: String, isDaemon: Boolean, routine: ThreadRoutine): Thread =
|
public actual val current: ThreadLocalMethods
|
||||||
DrivenPlatformThread(name, isDaemon, routine)
|
get() = this._tl_currentThread.get()?._threadLocalMethods ?: throw RuntimeException("This java thread can't be wrapped")
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
public actual fun currentThread(): Thread =
|
public actual fun create(name: String, isDaemon: Boolean, routine: ThreadRoutine): Thread =
|
||||||
this._tl_currentThread.get() ?: throw RuntimeException("This java thread can't be wrapped")
|
DrivenPlatformThread(name, isDaemon, routine)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private inner class ThreadLocalMethodsImpl : ThreadLocalMethods {
|
||||||
|
private fun _assertThread() {
|
||||||
|
if (Thread._tl_currentThread.get() != this@Thread)
|
||||||
|
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 var _fibersStack: _FibersStackNode? = null
|
||||||
|
|
||||||
|
override val runningFiber: Fiber?
|
||||||
|
get() {
|
||||||
|
this._assertThread()
|
||||||
|
return this._fibersStack?.fiber
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun enterFiber(fiberToEnter: Fiber, privateToken: Any): Fiber? {
|
||||||
|
this._assertThread()
|
||||||
|
val caller = this._fibersStack
|
||||||
|
this._fibersStack = _FibersStackNode(caller, fiberToEnter, privateToken)
|
||||||
|
return caller?.fiber
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun exitFiber(fiberToExit: Fiber, privateToken: Any, fiberToRestore: Fiber?) {
|
||||||
|
this._assertThread()
|
||||||
|
|
||||||
|
val top = this._fibersStack
|
||||||
|
if (top == null)
|
||||||
|
throw IllegalStateException("There is no running fiber to exit")
|
||||||
|
|
||||||
|
top.assertExit(fiberToExit, privateToken, fiberToRestore)
|
||||||
|
|
||||||
|
this._fibersStack = top.caller
|
||||||
|
}
|
||||||
|
|
||||||
|
private var _runningEventLoop: SingleThreadEventLoop? = null
|
||||||
|
private var _runningEventLoopToken: Any? = null
|
||||||
|
|
||||||
|
override val runningEventLoop: SingleThreadEventLoop?
|
||||||
|
get() {
|
||||||
|
this._assertThread()
|
||||||
|
return this._runningEventLoop
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun setEventLoop(eventLoop: SingleThreadEventLoop, privateToken: Any) {
|
||||||
|
this._assertThread()
|
||||||
|
if (this._runningEventLoop != null)
|
||||||
|
throw IllegalStateException("There is already a running event loop here")
|
||||||
|
this._runningEventLoop = eventLoop
|
||||||
|
this._runningEventLoopToken = privateToken
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun clearEventLoop(eventLoop: SingleThreadEventLoop, privateToken: Any) {
|
||||||
|
this._assertThread()
|
||||||
|
if (this._runningEventLoop !== eventLoop)
|
||||||
|
throw IllegalStateException("Currently another event loop is running")
|
||||||
|
if (this._runningEventLoopToken !== privateToken)
|
||||||
|
throw IllegalArgumentException("privateToken doesn't match")
|
||||||
|
|
||||||
|
this._runningEventLoop = null
|
||||||
|
this._runningEventLoopToken = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
package ru.landgrafhomyak.multitasking_0.threads
|
||||||
|
|
||||||
|
import ru.landgrafhomyak.multitasking_0.Fiber
|
||||||
|
import ru.landgrafhomyak.multitasking_0.SingleThreadEventLoop
|
||||||
|
|
||||||
|
public actual sealed interface ThreadLocalMethods {
|
||||||
|
public actual fun get(): Thread
|
||||||
|
|
||||||
|
public actual val runningFiber: Fiber?
|
||||||
|
public actual fun enterFiber(fiberToEnter: Fiber, privateToken: Any): Fiber?
|
||||||
|
public actual fun exitFiber(fiberToExit: Fiber, privateToken: Any, fiberToRestore: Fiber?)
|
||||||
|
|
||||||
|
public actual val runningEventLoop: SingleThreadEventLoop?
|
||||||
|
public actual fun setEventLoop(eventLoop: SingleThreadEventLoop, privateToken: Any)
|
||||||
|
public actual fun clearEventLoop(eventLoop: SingleThreadEventLoop, privateToken: Any)
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
package ru.landgrafhomyak.multitasking_0.threads.impl.java_virtual_threads
|
package ru.landgrafhomyak.multitasking_0.threads.impl.java_virtual_threads
|
||||||
|
|
||||||
|
import java.lang.Object as jObject
|
||||||
import java.lang.Thread as jThread
|
import java.lang.Thread as jThread
|
||||||
import java.util.concurrent.locks.Condition
|
import java.util.concurrent.locks.Condition
|
||||||
import java.util.concurrent.locks.ReentrantLock
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
@ -7,6 +8,7 @@ import kotlin.concurrent.withLock
|
|||||||
import ru.landgrafhomyak.multitasking_0.ExecutionState
|
import ru.landgrafhomyak.multitasking_0.ExecutionState
|
||||||
import ru.landgrafhomyak.multitasking_0.Fiber
|
import ru.landgrafhomyak.multitasking_0.Fiber
|
||||||
import ru.landgrafhomyak.multitasking_0.FiberRoutine
|
import ru.landgrafhomyak.multitasking_0.FiberRoutine
|
||||||
|
import ru.landgrafhomyak.multitasking_0.WrongCallerThreadException
|
||||||
import ru.landgrafhomyak.multitasking_0.threads.Thread as wThread
|
import ru.landgrafhomyak.multitasking_0.threads.Thread as wThread
|
||||||
|
|
||||||
public class JavaVirtualThreadFiber : Fiber {
|
public class JavaVirtualThreadFiber : Fiber {
|
||||||
@ -64,7 +66,7 @@ public class JavaVirtualThreadFiber : Fiber {
|
|||||||
|
|
||||||
override fun yield() {
|
override fun yield() {
|
||||||
if (jThread.currentThread() !== this._thisVThread)
|
if (jThread.currentThread() !== this._thisVThread)
|
||||||
TODO("err")
|
throw WrongCallerThreadException("yield() must be called only inside it's fiber")
|
||||||
|
|
||||||
this._syncLock.withLock {
|
this._syncLock.withLock {
|
||||||
when (this._state) {
|
when (this._state) {
|
||||||
@ -101,15 +103,15 @@ public class JavaVirtualThreadFiber : Fiber {
|
|||||||
ExecutionState.FINISHED_SUCCESSFULLY, ExecutionState.FINISHED_WITH_ERROR -> throw IllegalStateException("Fiber already finished")
|
ExecutionState.FINISHED_SUCCESSFULLY, ExecutionState.FINISHED_WITH_ERROR -> throw IllegalStateException("Fiber already finished")
|
||||||
}
|
}
|
||||||
|
|
||||||
val currentThread = wThread.currentThread()
|
val token = jObject()
|
||||||
this._resumedOnThread = currentThread
|
val currentThread = wThread.current
|
||||||
this._resumedOnFiber = currentThread.runningFiber
|
this._resumedOnThread = currentThread.get()
|
||||||
currentThread.runningFiber = this
|
this._resumedOnFiber = currentThread.enterFiber(this, token)
|
||||||
|
|
||||||
this._syncCond.signal()
|
this._syncCond.signal()
|
||||||
this._syncCond.await()
|
this._syncCond.await()
|
||||||
|
|
||||||
currentThread.runningFiber = this._resumedOnFiber
|
currentThread.exitFiber(this, token, this.resumedOnFiber)
|
||||||
this._resumedOnThread = null
|
this._resumedOnThread = null
|
||||||
this._resumedOnFiber = null
|
this._resumedOnFiber = null
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,33 +3,104 @@ package ru.landgrafhomyak.multitasking_0.threads
|
|||||||
import kotlin.experimental.ExpectRefinement
|
import kotlin.experimental.ExpectRefinement
|
||||||
import ru.landgrafhomyak.multitasking_0.Fiber
|
import ru.landgrafhomyak.multitasking_0.Fiber
|
||||||
|
|
||||||
|
|
||||||
// didn't work because AMBIGUOUS_EXPECTS
|
// didn't work because AMBIGUOUS_EXPECTS
|
||||||
@OptIn(ExperimentalMultiplatform::class)
|
@OptIn(ExperimentalMultiplatform::class)
|
||||||
@ExpectRefinement
|
@ExpectRefinement
|
||||||
public expect class Thread {
|
public expect class Thread {
|
||||||
|
/**
|
||||||
|
* Name of thread for debug purposes.
|
||||||
|
*
|
||||||
|
* After [releaseResources()][Thread.releaseResources] become inaccessible.
|
||||||
|
*/
|
||||||
public val name: String
|
public val name: String
|
||||||
override fun toString(): String
|
override fun toString(): String
|
||||||
public var runningFiber: Fiber?
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start execution of [routine][ThreadRoutine] passed to [create()][Thread.create].
|
||||||
|
*
|
||||||
|
* Doesn't define when any resources used by underlying functionality (e.g., stack) must be allocated.
|
||||||
|
*/
|
||||||
public fun start()
|
public fun start()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blocks caller thread or fiber until [releaseResources()][Thread.releaseResources] call allowed.
|
||||||
|
*
|
||||||
|
* Calling this method before thread [started][Thread.start] is error.
|
||||||
|
*/
|
||||||
public fun join()
|
public fun join()
|
||||||
public val state: State
|
|
||||||
public val uncaughtException: Throwable
|
/**
|
||||||
|
* Confirms that all resources used by underlying functionality are released.
|
||||||
|
* Can be called only once.
|
||||||
|
* Can be called before thread [started][Thread.start] or after thread [finishes][Thread.join].
|
||||||
|
*/
|
||||||
public fun releaseResources()
|
public fun releaseResources()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State of thread. Always accessible.
|
||||||
|
*/
|
||||||
|
public val state: State
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception that wasn't uncaught by [routine][ThreadRoutine] and terminated thread.
|
||||||
|
*
|
||||||
|
* Accessible only in [FINISHED_WITH_ERROR][Thread.State.FINISHED_WITH_ERROR] state,
|
||||||
|
* in other [states][Thread.state] will throw error, even after [releaseResources()][Thread.releaseResources].
|
||||||
|
*/
|
||||||
|
public val uncaughtException: Throwable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns `false` if thread prevents process from being finished while thread is running.
|
||||||
|
*
|
||||||
|
* After [releaseResources()][Thread.releaseResources] become inaccessible.
|
||||||
|
*/
|
||||||
public val isDaemon: Boolean
|
public val isDaemon: Boolean
|
||||||
|
|
||||||
public enum class State {
|
public enum class State {
|
||||||
|
/**
|
||||||
|
* Thread [created][Thread.create] but not [started][Thread.start] yet.
|
||||||
|
*/
|
||||||
NEW,
|
NEW,
|
||||||
NOT_FINISHED,
|
/**
|
||||||
|
* Thread [started][Thread.start], but not finished yet.
|
||||||
|
*/
|
||||||
|
STARTED,
|
||||||
|
/**
|
||||||
|
* Thread finished ([routine][ThreadRoutine] returned) normally.
|
||||||
|
*/
|
||||||
FINISHED_SUCCESSFULLY,
|
FINISHED_SUCCESSFULLY,
|
||||||
|
/**
|
||||||
|
* Thread [finished with error][Thread.uncaughtException], that wasn't caught by [routine][ThreadRoutine].
|
||||||
|
*/
|
||||||
FINISHED_WITH_ERROR,
|
FINISHED_WITH_ERROR,
|
||||||
|
/**
|
||||||
|
* All resources allocated by this [Thread] object are released and reference to descriptor can be lost.
|
||||||
|
*/
|
||||||
DESTROYED
|
DESTROYED
|
||||||
}
|
}
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
|
/**
|
||||||
|
* Thread-local getter that returns object with access to some thread-local meta-information.
|
||||||
|
*
|
||||||
|
* Passing this object to another thread is not allowed and his members will throw error.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* ***Java's [virtual threads](https://docs.oracle.com/en/java/javase/21/core/virtual-threads.html) note:***
|
||||||
|
* If called inside [virtual thread used as fiber][ru.landgrafhomyak.multitasking_0.threads.impl.java_virtual_threads.JavaVirtualThreadFiber],
|
||||||
|
* it will return object associated with [Fiber.resumedOnThread] instead of actual thread.
|
||||||
|
* If a virtual thread is created another way, it will return its own descriptor.
|
||||||
|
*/
|
||||||
|
public val current: ThreadLocalMethods
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new [thread][Thread] in [unstarted][Thread.State.NEW] state.
|
||||||
|
*
|
||||||
|
* @param name name of thread for debug purposes.
|
||||||
|
* @param isDaemon should thread prevent process from being finished while thread is running.
|
||||||
|
* @param routine
|
||||||
|
*/
|
||||||
public fun create(name: String, isDaemon: Boolean, routine: ThreadRoutine): Thread
|
public fun create(name: String, isDaemon: Boolean, routine: ThreadRoutine): Thread
|
||||||
public fun currentThread(): Thread
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user