-
Notifications
You must be signed in to change notification settings - Fork 106
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
260 additions
and
155 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
72 changes: 72 additions & 0 deletions
72
src/main/kotlin/org/jetbrains/kotlinx/jupyter/execution.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package org.jetbrains.kotlinx.jupyter | ||
|
||
import kotlinx.coroutines.CoroutineScope | ||
import kotlinx.coroutines.Dispatchers | ||
import kotlinx.coroutines.launch | ||
import org.jetbrains.kotlinx.jupyter.exceptions.ReplException | ||
import java.util.Collections | ||
import java.util.concurrent.ConcurrentHashMap | ||
import kotlin.concurrent.thread | ||
|
||
sealed interface ExecutionResult<out T> { | ||
class Success<out T>(val result: T) : ExecutionResult<T> | ||
class Failure(val throwable: Throwable) : ExecutionResult<Nothing> | ||
object Interrupted : ExecutionResult<Nothing> | ||
} | ||
|
||
interface JupyterExecutor { | ||
fun <T> runExecution(classLoader: ClassLoader? = null, body: () -> T): ExecutionResult<T> | ||
fun interruptExecutions() | ||
|
||
fun launchJob(runnable: suspend CoroutineScope.() -> Unit) | ||
} | ||
|
||
class JupyterExecutorImpl : JupyterExecutor { | ||
private val currentExecutions: MutableSet<Thread> = Collections.newSetFromMap(ConcurrentHashMap()) | ||
private val coroutineScope = CoroutineScope(Dispatchers.Default) | ||
|
||
override fun <T> runExecution(classLoader: ClassLoader?, body: () -> T): ExecutionResult<T> { | ||
var execRes: T? = null | ||
var execException: Throwable? = null | ||
val execThread = thread(contextClassLoader = classLoader ?: Thread.currentThread().contextClassLoader) { | ||
try { | ||
execRes = body() | ||
} catch (e: Throwable) { | ||
execException = e | ||
} | ||
} | ||
currentExecutions.add(execThread) | ||
execThread.join() | ||
currentExecutions.remove(execThread) | ||
|
||
val exception = execException | ||
|
||
return if (exception == null) { | ||
ExecutionResult.Success(execRes!!) | ||
} else { | ||
val isInterrupted = exception is ThreadDeath || | ||
(exception is ReplException && exception.cause is ThreadDeath) | ||
if (isInterrupted) ExecutionResult.Interrupted | ||
else ExecutionResult.Failure(exception) | ||
} | ||
} | ||
|
||
/** | ||
* We cannot use [Thread.interrupt] here because we have no way | ||
* to control the code user executes. [Thread.interrupt] will do nothing for | ||
* the simple calculation (like `while (true) 1`). Consider replacing with | ||
* something more smart in the future. | ||
*/ | ||
override fun interruptExecutions() { | ||
@Suppress("deprecation") | ||
while (currentExecutions.isNotEmpty()) { | ||
val execution = currentExecutions.firstOrNull() | ||
execution?.stop() | ||
currentExecutions.remove(execution) | ||
} | ||
} | ||
|
||
override fun launchJob(runnable: suspend CoroutineScope.() -> Unit) { | ||
coroutineScope.launch(block = runnable) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.