package kernel.ps; import kernel.turtle.TurtleMutex; import kernel.ps.ProcessManager.PID; import kernel.ui.WindowContext; import kernel.ui.WindowManager; import haxe.ds.ReadOnlyArray; using tink.CoreApi; typedef HandleConfig = { ?args:Array, ?onWrite:Callback, ?onExit:Callback, } class ProcessHandle { public var args(get, null):ReadOnlyArray; private final pid:PID; private final config:HandleConfig; private final closeFuture:Future; private var closeFutureResolev:Bool->Void; private final windowContexts:Array = []; private final cbLinks:Array = []; private final deferFuncs:ArrayVoid> = []; private var hasExited:Bool = false; @:allow(kernel.ps.ProcessManager) private function new(config:HandleConfig, pid:PID) { this.config = config; this.pid = pid; this.closeFuture = new Future((trigger) -> { this.closeFutureResolev = trigger; return null; }); if (this.config.onExit != null) { this.closeFuture.handle(this.config.onExit); } } public function onExit():Future { return this.closeFuture; } public function close(success:Bool = true):Void { this.hasExited = true; this.dispose(); EndOfLoop.endOfLoop(() -> { this.closeFutureResolev(success); }); ProcessManager.removeProcess(this.pid); } public function write(message:String):Void { if (this.hasExited) return; if (this.config.onWrite != null) { this.config.onWrite.invoke(message); } } public function writeLine(message:String):Void { this.write(message + "\n"); } public function createBufferdWindowContext():WindowContext { var ctx = WindowManager.createNewContext(); this.windowContexts.push(ctx); return ctx; } public function createStatelessWindowContext():{ctx:WindowContext, setRenderFunc:(() -> Void)->Void, requestRender:() -> Void} { var ctx = WindowManager.createNewStatelessContext(); this.windowContexts.push(ctx.ctx); return ctx; } public function getWindowContexts():ReadOnlyArray { return this.windowContexts; } private function dispose() { for (link in this.cbLinks) { link.cancel(); } for (func in this.deferFuncs) { func(); } } public function getPid():PID { return this.pid; } public function addCallbackLink(link:CallbackLink) { this.cbLinks.push(link); } public function addDeferFunc(func:Void->Void) { this.deferFuncs.push(func); } public function get_args():ReadOnlyArray { return this.config.args; } public function claimTurtleMutex():Bool { if (TurtleMutex.claim(this.pid)) { this.addDeferFunc(() -> { TurtleMutex.release(this.pid); }); return true; } return false; } }