1
1
package org.jetbrains.kotlinx.jupyter
2
2
3
- import kotlinx.coroutines.CoroutineScope
4
- import kotlinx.coroutines.Dispatchers
5
- import kotlinx.coroutines.launch
6
3
import kotlinx.serialization.decodeFromString
7
4
import kotlinx.serialization.encodeToString
8
5
import kotlinx.serialization.json.Json
@@ -15,7 +12,6 @@ import org.jetbrains.kotlinx.jupyter.api.libraries.RawMessage
15
12
import org.jetbrains.kotlinx.jupyter.api.libraries.RawMessageCallback
16
13
import org.jetbrains.kotlinx.jupyter.api.libraries.header
17
14
import org.jetbrains.kotlinx.jupyter.api.libraries.type
18
- import org.jetbrains.kotlinx.jupyter.exceptions.ReplException
19
15
import org.jetbrains.kotlinx.jupyter.messaging.InputReply
20
16
import org.jetbrains.kotlinx.jupyter.messaging.InputRequest
21
17
import org.jetbrains.kotlinx.jupyter.messaging.JupyterConnectionInternal
@@ -29,6 +25,7 @@ import org.jetbrains.kotlinx.jupyter.messaging.emptyJsonObjectStringBytes
29
25
import org.jetbrains.kotlinx.jupyter.messaging.jsonObject
30
26
import org.jetbrains.kotlinx.jupyter.messaging.makeJsonHeader
31
27
import org.jetbrains.kotlinx.jupyter.messaging.makeReplyMessage
28
+ import org.jetbrains.kotlinx.jupyter.messaging.makeSimpleMessage
32
29
import org.jetbrains.kotlinx.jupyter.messaging.sendMessage
33
30
import org.jetbrains.kotlinx.jupyter.messaging.toMessage
34
31
import org.jetbrains.kotlinx.jupyter.messaging.toRawMessage
@@ -37,10 +34,10 @@ import org.zeromq.SocketType
37
34
import org.zeromq.ZMQ
38
35
import java.io.Closeable
39
36
import java.io.IOException
37
+ import java.io.InputStream
40
38
import java.security.SignatureException
41
39
import javax.crypto.Mac
42
40
import javax.crypto.spec.SecretKeySpec
43
- import kotlin.concurrent.thread
44
41
import kotlin.math.min
45
42
46
43
typealias SocketMessageCallback = JupyterConnectionImpl .Socket .(Message ) -> Unit
@@ -106,14 +103,8 @@ class JupyterConnectionImpl(
106
103
}
107
104
}
108
105
109
- fun sendStatus (status : KernelStatus , msg : Message ) {
110
- connection.iopub.sendMessage(makeReplyMessage(msg, MessageType .STATUS , content = StatusReply (status)))
111
- }
112
-
113
106
fun sendWrapped (incomingMessage : Message , msg : Message ) {
114
- sendStatus(KernelStatus .BUSY , incomingMessage)
115
- sendMessage(msg)
116
- sendStatus(KernelStatus .IDLE , incomingMessage)
107
+ doWrappedInBusyIdle(incomingMessage) { sendMessage(msg) }
117
108
}
118
109
119
110
override fun sendRawMessage (msg : RawMessage ) {
@@ -140,7 +131,7 @@ class JupyterConnectionImpl(
140
131
override val connection: JupyterConnectionImpl = this @JupyterConnectionImpl
141
132
}
142
133
143
- inner class StdinInputStream : java.io. InputStream () {
134
+ inner class StdinInputStream : InputStream () {
144
135
private var currentBuf: ByteArray? = null
145
136
private var currentBufPos = 0
146
137
@@ -263,57 +254,26 @@ class JupyterConnectionImpl(
263
254
send(socketName, message)
264
255
}
265
256
266
- val stdinIn = StdinInputStream ()
267
-
268
- var contextMessage: Message ? = null
269
-
270
- private val currentExecutions = HashSet <Thread >()
271
- private val coroutineScope = CoroutineScope (Dispatchers .Default )
272
-
273
- data class ConnectionExecutionResult <T >(
274
- val result : T ? ,
275
- val throwable : Throwable ? ,
276
- val isInterrupted : Boolean ,
277
- )
278
-
279
- fun <T > runExecution (body : () -> T , classLoader : ClassLoader ): ConnectionExecutionResult <T > {
280
- var execRes: T ? = null
281
- var execException: Throwable ? = null
282
- val execThread = thread(contextClassLoader = classLoader) {
283
- try {
284
- execRes = body()
285
- } catch (e: Throwable ) {
286
- execException = e
287
- }
288
- }
289
- currentExecutions.add(execThread)
290
- execThread.join()
291
- currentExecutions.remove(execThread)
292
-
293
- val exception = execException
294
- val isInterrupted = exception is ThreadDeath ||
295
- (exception is ReplException && exception.cause is ThreadDeath )
296
- return ConnectionExecutionResult (execRes, exception, isInterrupted)
257
+ override fun sendStatus (status : KernelStatus , incomingMessage : Message ? ) {
258
+ val message = if (incomingMessage != null ) makeReplyMessage(incomingMessage, MessageType .STATUS , content = StatusReply (status))
259
+ else makeSimpleMessage(MessageType .STATUS , content = StatusReply (status))
260
+ iopub.sendMessage(message)
297
261
}
298
262
299
- /* *
300
- * We cannot use [Thread.interrupt] here because we have no way
301
- * to control the code user executes. [Thread.interrupt] will do nothing for
302
- * the simple calculation (like `while (true) 1`). Consider replacing with
303
- * something more smart in the future.
304
- */
305
- fun interruptExecution () {
306
- @Suppress(" deprecation" )
307
- while (currentExecutions.isNotEmpty()) {
308
- val execution = currentExecutions.firstOrNull()
309
- execution?.stop()
310
- currentExecutions.remove(execution)
263
+ override fun doWrappedInBusyIdle (incomingMessage : Message ? , action : () -> Unit ) {
264
+ sendStatus(KernelStatus .BUSY , incomingMessage)
265
+ try {
266
+ action()
267
+ } finally {
268
+ sendStatus(KernelStatus .IDLE , incomingMessage)
311
269
}
312
270
}
313
271
314
- fun launchJob (runnable : suspend CoroutineScope .() -> Unit ) {
315
- coroutineScope.launch(block = runnable)
316
- }
272
+ override val stdinIn = StdinInputStream ()
273
+
274
+ var contextMessage: Message ? = null
275
+
276
+ override val executor: JupyterExecutor = JupyterExecutorImpl ()
317
277
318
278
override fun close () {
319
279
heartbeat.close()
@@ -399,7 +359,7 @@ fun ZMQ.Socket.receiveRawMessage(start: ByteArray, hmac: HMAC): RawMessage {
399
359
)
400
360
}
401
361
402
- object DisabledStdinInputStream : java.io. InputStream() {
362
+ object DisabledStdinInputStream : InputStream() {
403
363
override fun read (): Int {
404
364
throw IOException (" Input from stdin is unsupported by the client" )
405
365
}
0 commit comments