Thread implementation on java
This commit is contained in:
parent
9d847df01c
commit
cfcf761745
@ -1,6 +1,4 @@
|
||||
import ru.landgrafhomyak.kotlin.kmp_gradle_build_helper.configureAllCompilationsOnAllTargets
|
||||
import ru.landgrafhomyak.kotlin.kmp_gradle_build_helper.configureAllCompilersOptionsOnAllTargets
|
||||
import ru.landgrafhomyak.kotlin.kmp_gradle_build_helper.defineAllMultiplatformTargets
|
||||
import ru.landgrafhomyak.kotlin.kmp_gradle_build_helper.defineXomrkGiteaMavenRepo
|
||||
|
||||
buildscript {
|
||||
@ -15,7 +13,7 @@ buildscript {
|
||||
}
|
||||
|
||||
plugins {
|
||||
kotlin("multiplatform") version "2.2.10"
|
||||
kotlin("multiplatform") version "2.2.20-Beta1"
|
||||
`maven-publish`
|
||||
}
|
||||
|
||||
@ -42,7 +40,7 @@ kotlin {
|
||||
|
||||
|
||||
configureAllCompilersOptionsOnAllTargets {
|
||||
freeCompilerArgs.addAll("-Xexpect-actual-classes")
|
||||
freeCompilerArgs.addAll("-Xexpect-actual-classes", "-Xrender-internal-diagnostic-names", "-XXLanguage:+ExpectRefinement")
|
||||
}
|
||||
|
||||
jvm().compilations.configureEach {
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
package ru.landgrafhomyak.multitasking_0
|
||||
|
||||
import ru.landgrafhomyak.multitasking_0.threads.Thread
|
||||
|
||||
/**
|
||||
* Concurrency primitive with call stack.
|
||||
*/
|
||||
public interface Fiber {
|
||||
/**
|
||||
* Returns [thread][Thread] to which fiber is bound if there are restrictions to threads where fiber can be [resumed][Fiber.resume].
|
||||
* Returns [thread][ru.landgrafhomyak.multitasking_0.threads.Thread] to which fiber is bound if there are restrictions to threads where fiber can be [resumed][Fiber.resume].
|
||||
*/
|
||||
public val ownerThread: Thread?
|
||||
|
||||
@ -59,9 +61,13 @@ public interface Fiber {
|
||||
*/
|
||||
public fun resume()
|
||||
|
||||
public fun interrupt()
|
||||
|
||||
/**
|
||||
* Returns uncaught exception that terminated this fiber.
|
||||
* If current [state][Fiber.state] isn't [FINISHED_WITH_ERROR][ExecutionState.FINISHED_WITH_ERROR] will throw [IllegalStateException].
|
||||
*/
|
||||
public val uncaughtException: Throwable
|
||||
|
||||
public fun releaseResources()
|
||||
}
|
||||
@ -1,5 +1,7 @@
|
||||
package ru.landgrafhomyak.multitasking_0
|
||||
|
||||
import ru.landgrafhomyak.multitasking_0.threads.Thread
|
||||
|
||||
public interface SingleThreadEventLoop {
|
||||
/**
|
||||
* Returns thread on which this event loop runs.
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
package ru.landgrafhomyak.multitasking_0
|
||||
package ru.landgrafhomyak.multitasking_0.threads
|
||||
|
||||
import ru.landgrafhomyak.multitasking_0.Fiber
|
||||
|
||||
public expect class Thread {
|
||||
public val name: String
|
||||
@ -7,6 +9,6 @@ public expect class Thread {
|
||||
public var runningFiber: Fiber?
|
||||
|
||||
public companion object {
|
||||
public fun getCurrentThread(): Thread
|
||||
public fun currentThread(): Thread
|
||||
}
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
package ru.landgrafhomyak.multitasking_0
|
||||
|
||||
public actual class Thread(
|
||||
public actual val name: String,
|
||||
) {
|
||||
actual override fun toString(): String = TODO()
|
||||
|
||||
public actual var runningFiber: Fiber? = null
|
||||
|
||||
public actual companion object {
|
||||
public actual fun getCurrentThread(): Thread = TODO()
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,122 @@
|
||||
package ru.landgrafhomyak.multitasking_0.threads
|
||||
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.lang.Thread as jThread
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
import kotlin.concurrent.withLock
|
||||
|
||||
@Suppress("JoinDeclarationAndAssignment")
|
||||
internal class DrivenPlatformThread : Thread {
|
||||
override fun toString(): String = TODO()
|
||||
|
||||
override val _nativeThread: jThread
|
||||
|
||||
private val _sync: ReentrantLock
|
||||
private var _uncaughtException: Throwable?
|
||||
private var _isExplicitlyDestroyed: Boolean
|
||||
private val _threadFinishedWaiter: CountDownLatch
|
||||
|
||||
internal constructor(name: String, isDaemon: Boolean, routine: ThreadRoutine) : super() {
|
||||
this._sync = ReentrantLock()
|
||||
this._uncaughtException = null
|
||||
this._isExplicitlyDestroyed = false
|
||||
this._threadFinishedWaiter = CountDownLatch(1)
|
||||
|
||||
this._nativeThread = jThread.ofPlatform().name(name).daemon(isDaemon).unstarted(this.Kernel(routine))
|
||||
}
|
||||
|
||||
private inner class Kernel(private val _routine: ThreadRoutine) : Runnable {
|
||||
override fun run() {
|
||||
try {
|
||||
this._routine.runThread(this@DrivenPlatformThread)
|
||||
} catch (t: Throwable) {
|
||||
this@DrivenPlatformThread._sync.withLock {
|
||||
this@DrivenPlatformThread._uncaughtException = t
|
||||
}
|
||||
} finally {
|
||||
this@DrivenPlatformThread._threadFinishedWaiter.countDown()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override val state: State
|
||||
get() {
|
||||
this._sync.withLock {
|
||||
if (this._isExplicitlyDestroyed)
|
||||
return State.DESTROYED
|
||||
|
||||
when (this._nativeThread.state) {
|
||||
jThread.State.NEW -> return State.NEW
|
||||
jThread.State.RUNNABLE -> return State.NOT_FINISHED
|
||||
jThread.State.BLOCKED -> return State.NOT_FINISHED
|
||||
jThread.State.WAITING -> return State.NOT_FINISHED
|
||||
jThread.State.TIMED_WAITING -> return State.NOT_FINISHED
|
||||
jThread.State.TERMINATED -> {
|
||||
if (this._uncaughtException == null)
|
||||
return State.FINISHED_SUCCESSFULLY
|
||||
else
|
||||
return State.FINISHED_WITH_ERROR
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override val uncaughtException: Throwable
|
||||
get() {
|
||||
this._sync.withLock {
|
||||
val e = this._uncaughtException
|
||||
if (e != null)
|
||||
return e
|
||||
|
||||
when (this._nativeThread.state) {
|
||||
jThread.State.NEW, jThread.State.RUNNABLE, jThread.State.BLOCKED, jThread.State.WAITING, jThread.State.TIMED_WAITING ->
|
||||
throw IllegalStateException("Thread not finished yet")
|
||||
|
||||
jThread.State.TERMINATED -> throw IllegalStateException("Thread finished without uncaught exceptions")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun start() {
|
||||
this._sync.withLock {
|
||||
if (this._isExplicitlyDestroyed)
|
||||
throw IllegalStateException("Thread already was started, finished and destroyed")
|
||||
// stdlib's errors aren't verbose
|
||||
when (this._nativeThread.state) {
|
||||
jThread.State.NEW -> {}
|
||||
jThread.State.TERMINATED -> throw IllegalStateException("Thread already was started and finished")
|
||||
jThread.State.RUNNABLE, jThread.State.BLOCKED, jThread.State.WAITING, jThread.State.TIMED_WAITING ->
|
||||
throw IllegalStateException("Thread already was started")
|
||||
}
|
||||
|
||||
this._nativeThread.start()
|
||||
}
|
||||
}
|
||||
|
||||
override fun join() {
|
||||
this._sync.withLock {
|
||||
if (this._isExplicitlyDestroyed)
|
||||
throw IllegalStateException("Can't join on destroyed thread")
|
||||
if (this._nativeThread.state == jThread.State.NEW)
|
||||
throw IllegalStateException("Can't join on thread that isn't started")
|
||||
}
|
||||
|
||||
// stdlib's join uses Object.wait which may block caller virtual thread, so let wait in way virtual threads support
|
||||
this._threadFinishedWaiter.await()
|
||||
this._nativeThread.join()
|
||||
}
|
||||
|
||||
override fun releaseResources() {
|
||||
this._sync.withLock {
|
||||
if (this._isExplicitlyDestroyed)
|
||||
throw IllegalStateException("Thread already destroyed")
|
||||
when (this._nativeThread.state) {
|
||||
jThread.State.NEW -> {}
|
||||
jThread.State.TERMINATED -> {}
|
||||
jThread.State.RUNNABLE, jThread.State.BLOCKED, jThread.State.WAITING, jThread.State.TIMED_WAITING ->
|
||||
throw IllegalStateException("Thread already was started")
|
||||
}
|
||||
this._isExplicitlyDestroyed = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
package ru.landgrafhomyak.multitasking_0.threads
|
||||
|
||||
import java.lang.Thread as jThread
|
||||
import ru.landgrafhomyak.multitasking_0.Fiber
|
||||
|
||||
@Suppress("AMBIGUOUS_EXPECTS", "ACTUAL_WITHOUT_EXPECT")
|
||||
public actual sealed class Thread {
|
||||
actual abstract override fun toString(): String
|
||||
public actual var runningFiber: Fiber? = null
|
||||
|
||||
protected abstract val _nativeThread: jThread
|
||||
|
||||
public actual val name: String get() = this._nativeThread.name
|
||||
public actual val isDaemon: Boolean get() = this._nativeThread.isDaemon
|
||||
public actual abstract val state: State
|
||||
public actual abstract val uncaughtException: Throwable
|
||||
public actual abstract fun releaseResources()
|
||||
|
||||
public actual abstract fun start()
|
||||
|
||||
public actual abstract fun join()
|
||||
|
||||
public actual enum class State {
|
||||
NEW,
|
||||
NOT_FINISHED,
|
||||
FINISHED_SUCCESSFULLY,
|
||||
FINISHED_WITH_ERROR,
|
||||
DESTROYED
|
||||
}
|
||||
|
||||
public actual companion object {
|
||||
@JvmStatic
|
||||
public actual fun create(name: String, isDaemon: Boolean, routine: ThreadRoutine): Thread {
|
||||
TODO()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
public actual fun currentThread(): Thread {
|
||||
TODO()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package ru.landgrafhomyak.multitasking_0.threads
|
||||
|
||||
import kotlin.experimental.ExpectRefinement
|
||||
import ru.landgrafhomyak.multitasking_0.Fiber
|
||||
|
||||
|
||||
// didn't work because AMBIGUOUS_EXPECTS
|
||||
@OptIn(ExperimentalMultiplatform::class)
|
||||
@ExpectRefinement
|
||||
public expect class Thread {
|
||||
public val name: String
|
||||
override fun toString(): String
|
||||
public var runningFiber: Fiber?
|
||||
|
||||
public fun start()
|
||||
public fun join()
|
||||
public val state: State
|
||||
public val uncaughtException: Throwable
|
||||
public fun releaseResources()
|
||||
public val isDaemon: Boolean
|
||||
|
||||
public enum class State {
|
||||
NEW,
|
||||
NOT_FINISHED,
|
||||
FINISHED_SUCCESSFULLY,
|
||||
FINISHED_WITH_ERROR,
|
||||
DESTROYED
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public fun create(name: String, isDaemon: Boolean, routine: ThreadRoutine): Thread
|
||||
public fun currentThread(): Thread
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
package ru.landgrafhomyak.multitasking_0.threads
|
||||
|
||||
public fun interface ThreadRoutine {
|
||||
public fun runThread(thread: Thread)
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user