spy16 / slurp

Slurp is a highly customisable LISP toolkit for Go applications. 💻

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Implement Concurrency Primitives

spy16 opened this issue · comments

Concurrency primitives need to be decided.

Consider:

type GoExpr struct {
	Value value.Any
}

// Eval forks the given context to get a child context and launches goroutine
// with the child context to evaluate the Value.
func (ge GoExpr) Eval(ctx *Context) (value.Any, error) {
	child := ctx.fork()

        p := Promise{
                val: make(chan value.Any, 1)
                err: make(chan error, 1)
        }

	go func() {
                // N.B.:  we don't need to close any of the channels (see note below).
		if val, err := child.Eval(ge.Value); err != nil {
                    p.err <- err  // non-blocking due to buffer
                } else {
                    p.val <- val
                }
	}()
	return nil, nil
}

type Promise struct{
    // both channels are buffered (len=1)
    val chan value.Any
    err chan error
}

(p Promise) Eval(ctx *Context) (value.Any, err) {    return p, nil    }

(p Promise) Invoke(ctx *Context, args ...value.Any) (val value.Any, err error) {
    select {
    case val = <-p.val
    case err = <-p.err
    }
    return
}