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
}