Skip to content

Commit

Permalink
🦄 refactor: Move daemon thread to event loop
Browse files Browse the repository at this point in the history
  • Loading branch information
caoccao committed Nov 27, 2023
1 parent 40d1ae3 commit 6efb38d
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 62 deletions.
63 changes: 63 additions & 0 deletions console/src/main/kotlin/com/caoccao/javet/shell/BaseEventLoop.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2023. caoccao.com Sam Cao
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.caoccao.javet.shell

import com.caoccao.javet.enums.V8AwaitMode
import com.caoccao.javet.interfaces.IJavetClosable
import com.caoccao.javet.interop.V8Runtime
import com.caoccao.javet.shell.constants.Constants
import com.caoccao.javet.shell.entities.Options
import java.util.concurrent.TimeUnit

abstract class BaseEventLoop(
protected val v8Runtime: V8Runtime,
protected val options: Options,
) : IJavetClosable, Runnable {
private var daemonThread: Thread? = null

@Volatile
var running = false

override fun close() {
// Do nothing
}

override fun isClosed(): Boolean = !running

override fun run() {
while (running) {
v8Runtime.await(V8AwaitMode.RunOnce)
try {
TimeUnit.MILLISECONDS.sleep(Constants.Application.AWAIT_INTERVAL_IN_MILLIS)
} catch (t: Throwable) {
// Ignore
}
}
}

open fun start() {
running = true
daemonThread = Thread(this)
daemonThread?.start()
}

open fun stop() {
running = false
daemonThread?.join()
daemonThread = null
}
}
107 changes: 45 additions & 62 deletions console/src/main/kotlin/com/caoccao/javet/shell/BaseJavetShell.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

package com.caoccao.javet.shell

import com.caoccao.javet.enums.V8AwaitMode
import com.caoccao.javet.exceptions.JavetCompilationException
import com.caoccao.javet.exceptions.JavetExecutionException
import com.caoccao.javet.interop.V8Host
Expand All @@ -27,85 +26,69 @@ import com.caoccao.javet.shell.enums.ExitCode
import com.caoccao.javet.values.V8Value
import java.io.File
import java.util.*
import java.util.concurrent.TimeUnit

abstract class BaseJavetShell(
protected val options: Options,
) : Runnable {
) {
protected var v8Runtime: V8Runtime? = null

private var daemonThread: Thread? = null
protected abstract val prompt: String

@Volatile
private var running = false

abstract val prompt: String
protected abstract fun createEventLoop(v8Runtime: V8Runtime, options: Options): BaseEventLoop

fun execute(): ExitCode {
println("${Constants.Application.NAME} v${Constants.Application.VERSION} (${options.jsRuntimeType.name} ${options.jsRuntimeType.version})")
println("Please input the script or press Ctrl+C to exit.")
println()
V8Host.getInstance(options.jsRuntimeType).createV8Runtime<V8Runtime>().use { v8Runtime ->
running = true
this.v8Runtime = v8Runtime
registerPromiseRejectCallback()
daemonThread = Thread(this)
daemonThread?.start()
Scanner(System.`in`).use { scanner ->
val sb = StringBuilder()
var isMultiline = false
while (running) {
print(if (isMultiline) ">>> " else prompt)
try {
sb.appendLine(scanner.nextLine())
v8Runtime
.getExecutor(sb.toString())
.setResourceName(File(options.scriptName).absolutePath)
.setModule(options.module)
.execute<V8Value>()
.use { v8Value ->
println(v8Value.toString())
}
sb.clear()
isMultiline = false
} catch (e: JavetCompilationException) {
isMultiline = true
} catch (e: JavetExecutionException) {
sb.clear()
isMultiline = false
println()
println(e.scriptingError.toString())
println()
} catch (e: NoSuchElementException) {
println()
running = false
} catch (t: Throwable) {
sb.clear()
isMultiline = false
println()
println(t.message)
println()
createEventLoop(v8Runtime, options).use { eventLoop ->
this.v8Runtime = v8Runtime
registerPromiseRejectCallback()
eventLoop.start()
Scanner(System.`in`).use { scanner ->
val sb = StringBuilder()
var isMultiline = false
while (eventLoop.running) {
print(if (isMultiline) ">>> " else prompt)
try {
sb.appendLine(scanner.nextLine())
v8Runtime
.getExecutor(sb.toString())
.setResourceName(File(options.scriptName).absolutePath)
.setModule(options.module)
.execute<V8Value>()
.use { v8Value ->
println(v8Value.toString())
}
sb.clear()
isMultiline = false
} catch (e: JavetCompilationException) {
isMultiline = true
} catch (e: JavetExecutionException) {
sb.clear()
isMultiline = false
println()
println(e.scriptingError.toString())
println()
} catch (e: NoSuchElementException) {
println()
eventLoop.running = false
} catch (t: Throwable) {
sb.clear()
isMultiline = false
println()
println(t.message)
println()
}
}

}
eventLoop.stop()
this.v8Runtime = null
}
running = false
daemonThread?.join()
daemonThread = null
}
this.v8Runtime = null
return ExitCode.NoError
}

protected abstract fun registerPromiseRejectCallback()

override fun run() {
while (running) {
v8Runtime?.await(V8AwaitMode.RunOnce)
try {
TimeUnit.MILLISECONDS.sleep(Constants.Application.AWAIT_INTERVAL_IN_MILLIS)
} catch (t: Throwable) {
// Ignore
}
}
}
}
26 changes: 26 additions & 0 deletions console/src/main/kotlin/com/caoccao/javet/shell/EventLoopNode.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (c) 2023. caoccao.com Sam Cao
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.caoccao.javet.shell

import com.caoccao.javet.interop.V8Runtime
import com.caoccao.javet.shell.entities.Options

class EventLoopNode(
v8Runtime: V8Runtime,
options: Options,
) : BaseEventLoop(v8Runtime, options) {
}
26 changes: 26 additions & 0 deletions console/src/main/kotlin/com/caoccao/javet/shell/EventLoopV8.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (c) 2023. caoccao.com Sam Cao
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.caoccao.javet.shell

import com.caoccao.javet.interop.V8Runtime
import com.caoccao.javet.shell.entities.Options

class EventLoopV8(
v8Runtime: V8Runtime,
options: Options,
) : BaseEventLoop(v8Runtime, options) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.caoccao.javet.shell

import com.caoccao.javet.interop.V8Runtime
import com.caoccao.javet.interop.callback.JavetBuiltInModuleResolver
import com.caoccao.javet.shell.entities.Options

Expand All @@ -29,6 +30,10 @@ class JavetShellNode(
override val prompt: String
get() = "N > "

override fun createEventLoop(v8Runtime: V8Runtime, options: Options): BaseEventLoop {
return EventLoopNode(v8Runtime, options)
}

override fun registerPromiseRejectCallback() {
v8Runtime?.v8ModuleResolver = JavetBuiltInModuleResolver()
v8Runtime?.getExecutor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.caoccao.javet.shell

import com.caoccao.javet.interop.V8Runtime
import com.caoccao.javet.shell.entities.Options

class JavetShellV8(
Expand All @@ -28,6 +29,10 @@ class JavetShellV8(
override val prompt: String
get() = "V > "

override fun createEventLoop(v8Runtime: V8Runtime, options: Options): BaseEventLoop {
return EventLoopV8(v8Runtime, options)
}

override fun registerPromiseRejectCallback() {
v8Runtime?.setPromiseRejectCallback { _, _, value ->
System.err.println()
Expand Down

0 comments on commit 6efb38d

Please sign in to comment.