From 8a566444c4e3e75977bbb1629891b3fe594c3069 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Sun, 14 Jan 2018 00:27:48 +0100 Subject: non-blocking io --- cmd/eval/main.go | 2 +- cmd/j1e/main.go | 2 +- eval.go | 68 +++++++++++++++++++++++++++++++++++++++++++------------- eval_test.go | 2 +- 4 files changed, 56 insertions(+), 18 deletions(-) diff --git a/cmd/eval/main.go b/cmd/eval/main.go index 8d85a6f..b9518f3 100644 --- a/cmd/eval/main.go +++ b/cmd/eval/main.go @@ -7,5 +7,5 @@ func main() { if err := vm.LoadFile("testdata/j1e.bin"); err != nil { panic(err) } - vm.Eval() + vm.Run() } diff --git a/cmd/j1e/main.go b/cmd/j1e/main.go index 1d4c7ff..65cf626 100644 --- a/cmd/j1e/main.go +++ b/cmd/j1e/main.go @@ -7,5 +7,5 @@ import "dim13.org/j1" func main() { vm := j1.New() vm.LoadBytes(J1eBin) - vm.Eval() + vm.Run() } diff --git a/eval.go b/eval.go index 70426da..b40af46 100644 --- a/eval.go +++ b/eval.go @@ -18,11 +18,17 @@ type J1 struct { d stack r stack console io.ReadWriter - done bool + done chan struct{} + in, out chan uint16 } func New() *J1 { - return &J1{console: NewConsole()} + return &J1{ + console: NewConsole(), + done: make(chan struct{}), + in: make(chan uint16, 1), + out: make(chan uint16, 1), + } } // Reset VM @@ -48,15 +54,49 @@ func (j1 *J1) LoadFile(fname string) error { return j1.LoadBytes(data) } -// Eval evaluates content of memory -func (j1 *J1) Eval() { - for !j1.done { - ins := Decode(j1.memory[j1.pc]) - //fmt.Printf("%v\n%v", ins, j1) - j1.eval(ins) +func (j1 *J1) read() { + var b uint16 + for { + fmt.Fscanf(j1.console, "%c", &b) + select { + case <-j1.done: + return + case j1.in <- b: + } + } +} + +func (j1 *J1) write() { + for { + select { + case <-j1.done: + return + case b := <-j1.out: + fmt.Fprintf(j1.console, "%c", b) + } + } +} + +func (j1 *J1) run() { + for { + select { + case <-j1.done: + return + default: + ins := Decode(j1.memory[j1.pc]) + //fmt.Printf("%v\n%v", ins, j1) + j1.Eval(ins) + } } } +// Run evaluates content of memory +func (j1 *J1) Run() { + go j1.read() + go j1.write() + j1.run() +} + func (j1 *J1) String() string { s := fmt.Sprintf("\tPC=%0.4X ST=%0.4X\n", j1.pc, j1.st0) s += fmt.Sprintf("\tD=%0.4X\n", j1.d.dump()) @@ -70,9 +110,9 @@ func (j1 *J1) writeAt(addr, value uint16) { } switch addr { case 0xf000: // key - fmt.Fprintf(j1.console, "%c", value) + j1.out <- value case 0xf002: // bye - j1.done = true + close(j1.done) } } @@ -82,16 +122,14 @@ func (j1 *J1) readAt(addr uint16) uint16 { } switch addr { case 0xf000: // tx! - var b uint16 - fmt.Fscanf(j1.console, "%c", &b) - return b + return <-j1.in case 0xf001: // ?rx - return 1 + return uint16(len(j1.in)) } return 0 } -func (j1 *J1) eval(ins Instruction) { +func (j1 *J1) Eval(ins Instruction) { j1.pc++ switch v := ins.(type) { case Lit: diff --git a/eval_test.go b/eval_test.go index 60d3e1b..96d111e 100644 --- a/eval_test.go +++ b/eval_test.go @@ -114,7 +114,7 @@ func TestEval(t *testing.T) { t.Run(fmt.Sprint(tc.ins), func(t *testing.T) { state := New() for _, ins := range tc.ins { - state.eval(ins) + state.Eval(ins) } cmp(t, *state, tc.end) }) -- cgit v1.2.3