mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-12-14 12:10:30 +00:00
Be a little more rigorous in KotlinLuaMachine's threading
This commit is contained in:
parent
5ee5b11995
commit
1a87175ae7
@ -14,8 +14,6 @@ public enum UploadResult
|
||||
CONSUMED,
|
||||
ERROR;
|
||||
|
||||
public static final ITextComponent SUCCESS_TITLE = new TranslationTextComponent( "gui.computercraft.upload.success" );
|
||||
|
||||
public static final ITextComponent FAILED_TITLE = new TranslationTextComponent( "gui.computercraft.upload.failed" );
|
||||
public static final ITextComponent COMPUTER_OFF_MSG = new TranslationTextComponent( "gui.computercraft.upload.failed.computer_off" );
|
||||
public static final ITextComponent TOO_MUCH_MSG = new TranslationTextComponent( "gui.computercraft.upload.failed.too_much" );
|
||||
|
@ -116,8 +116,6 @@
|
||||
"gui.computercraft.tooltip.turn_off.key": "Hold Ctrl+S",
|
||||
"gui.computercraft.tooltip.terminate": "Stop the currently running code",
|
||||
"gui.computercraft.tooltip.terminate.key": "Hold Ctrl+T",
|
||||
"gui.computercraft.upload.success": "Upload Succeeded",
|
||||
"gui.computercraft.upload.success.msg": "%d files uploaded.",
|
||||
"gui.computercraft.upload.failed": "Upload Failed",
|
||||
"gui.computercraft.upload.failed.computer_off": "You must turn the computer on before uploading files.",
|
||||
"gui.computercraft.upload.failed.too_much": "Your files are too large to be uploaded.",
|
||||
|
@ -5,11 +5,9 @@ import dan200.computercraft.api.lua.ILuaContext
|
||||
import dan200.computercraft.core.lua.ILuaMachine
|
||||
import dan200.computercraft.core.lua.MachineEnvironment
|
||||
import dan200.computercraft.core.lua.MachineResult
|
||||
import kotlinx.coroutines.CoroutineName
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.*
|
||||
import java.io.InputStream
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
/**
|
||||
* An [ILuaMachine] which runs Kotlin functions instead.
|
||||
@ -26,7 +24,7 @@ abstract class KotlinLuaMachine(environment: MachineEnvironment) : ILuaMachine,
|
||||
queueEvent(eventName, arguments)
|
||||
} else {
|
||||
val task = getTask()
|
||||
if (task != null) CoroutineScope(Dispatchers.Unconfined + CoroutineName("Computer")).launch { task() }
|
||||
if (task != null) CoroutineScope(NeverDispatcher() + CoroutineName("Computer")).launch { task() }
|
||||
}
|
||||
|
||||
return MachineResult.OK
|
||||
@ -38,4 +36,20 @@ abstract class KotlinLuaMachine(environment: MachineEnvironment) : ILuaMachine,
|
||||
* Get the next task to execute on this computer.
|
||||
*/
|
||||
protected abstract fun getTask(): (suspend KotlinLuaMachine.() -> Unit)?
|
||||
|
||||
/**
|
||||
* A [CoroutineDispatcher] which only allows resuming from the computer thread. In practice, this means the only
|
||||
* way to yield is with [pullEvent].
|
||||
*/
|
||||
private class NeverDispatcher : CoroutineDispatcher() {
|
||||
private val expectedGroup = Thread.currentThread().threadGroup
|
||||
|
||||
override fun dispatch(context: CoroutineContext, block: Runnable) {
|
||||
if (Thread.currentThread().threadGroup != expectedGroup) {
|
||||
throw UnsupportedOperationException("Cannot perform arbitrary yields")
|
||||
}
|
||||
|
||||
block.run()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,9 +4,11 @@ import dan200.computercraft.api.lua.ILuaAPI
|
||||
import dan200.computercraft.api.lua.ILuaContext
|
||||
import dan200.computercraft.api.lua.MethodResult
|
||||
import dan200.computercraft.api.lua.ObjectArguments
|
||||
import dan200.computercraft.core.apis.OSAPI
|
||||
import dan200.computercraft.core.apis.PeripheralAPI
|
||||
import kotlinx.coroutines.CancellableContinuation
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import kotlin.time.Duration
|
||||
|
||||
/**
|
||||
* The context for tasks which consume Lua objects.
|
||||
@ -40,6 +42,19 @@ interface LuaTaskContext {
|
||||
/** Call a peripheral method. */
|
||||
suspend fun LuaTaskContext.callPeripheral(name: String, method: String, vararg args: Any?): Array<out Any?>? =
|
||||
getApi<PeripheralAPI>().call(context, ObjectArguments(name, method, *args)).await()
|
||||
|
||||
/**
|
||||
* Sleep for the given duration. This uses the internal computer clock, so won't be accurate.
|
||||
*/
|
||||
suspend fun LuaTaskContext.sleep(duration: Duration) {
|
||||
val timer = getApi<OSAPI>().startTimer(duration.inWholeMilliseconds / 1000.0)
|
||||
while (true) {
|
||||
val event = pullEvent("timer")
|
||||
if (event[0] == "timer" && event[1] is Number && (event[1] as Number).toInt() == timer) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Get a registered API. */
|
||||
|
Loading…
Reference in New Issue
Block a user