From 4f07f821e0d04e0cb6ec62d1d5bc3999dd7ba89a Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Mon, 15 Jan 2018 00:06:40 +0100 Subject: use context for cancelation --- console.go | 56 +++++++++++++++++++++++++++++++++++++++++++++++----- eval.go | 66 +++++++++++++++++++------------------------------------------- 2 files changed, 71 insertions(+), 51 deletions(-) diff --git a/console.go b/console.go index 5c63fbb..3b15a48 100644 --- a/console.go +++ b/console.go @@ -1,15 +1,61 @@ package j1 import ( + "context" + "fmt" "io" "os" ) -type Console struct { - io.Reader - io.Writer +type console struct { + r io.Reader + w io.Writer + ich, och chan uint16 } -func NewConsole() *Console { - return &Console{Reader: os.Stdin, Writer: os.Stdout} +func NewConsole(ctx context.Context) *console { + c := &console{ + r: os.Stdin, + w: os.Stdout, + ich: make(chan uint16, 1), + och: make(chan uint16, 1), + } + go c.read(ctx) + go c.write(ctx) + return c +} + +func (c *console) read(ctx context.Context) { + var v uint16 + for { + fmt.Fscanf(c.r, "%c", &v) + select { + case <-ctx.Done(): + return + case c.ich <- v: + } + } +} + +func (c *console) write(ctx context.Context) { + for { + select { + case <-ctx.Done(): + return + case v := <-c.och: + fmt.Fprintf(c.w, "%c", v) + } + } +} + +func (c *console) Read() uint16 { + return <-c.ich +} + +func (c *console) Write(v uint16) { + c.och <- v +} + +func (c *console) Len() uint16 { + return uint16(len(c.ich)) } diff --git a/eval.go b/eval.go index b40af46..b22012f 100644 --- a/eval.go +++ b/eval.go @@ -2,14 +2,20 @@ package j1 import ( "bytes" + "context" "encoding/binary" "fmt" - "io" "io/ioutil" ) const memSize = 0x4000 +type Console interface { + Read() uint16 + Write(uint16) + Len() uint16 +} + // J1 Forth processor VM type J1 struct { memory [memSize]uint16 // 0..0x3fff main memory, 0x4000 .. 0x7fff mem-mapped i/o @@ -17,18 +23,12 @@ type J1 struct { st0 uint16 // top of data stack d stack r stack - console io.ReadWriter - done chan struct{} - in, out chan uint16 + console Console + cancel context.CancelFunc } func New() *J1 { - return &J1{ - console: NewConsole(), - done: make(chan struct{}), - in: make(chan uint16, 1), - out: make(chan uint16, 1), - } + return new(J1) } // Reset VM @@ -54,33 +54,14 @@ func (j1 *J1) LoadFile(fname string) error { return j1.LoadBytes(data) } -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() { +// Run evaluates content of memory +func (j1 *J1) Run() { + ctx, cancel := context.WithCancel(context.Background()) + j1.console = NewConsole(ctx) + j1.cancel = cancel for { select { - case <-j1.done: + case <-ctx.Done(): return default: ins := Decode(j1.memory[j1.pc]) @@ -90,13 +71,6 @@ func (j1 *J1) run() { } } -// 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()) @@ -110,9 +84,9 @@ func (j1 *J1) writeAt(addr, value uint16) { } switch addr { case 0xf000: // key - j1.out <- value + j1.console.Write(value) case 0xf002: // bye - close(j1.done) + j1.cancel() } } @@ -122,9 +96,9 @@ func (j1 *J1) readAt(addr uint16) uint16 { } switch addr { case 0xf000: // tx! - return <-j1.in + return j1.console.Read() case 0xf001: // ?rx - return uint16(len(j1.in)) + return j1.console.Len() } return 0 } -- cgit v1.2.3