package react import "log" const testVersion = 4 type react struct { } type inputCell struct { cell } type compuCell struct { cell cb map[CallbackHandle]func(int) } type com struct { eval, ok chan bool } type cell struct { value int observer []com } func New() Reactor { return &react{} } func (r *react) CreateCompute1(c Cell, f func(int) int) ComputeCell { ch := make(chan bool) ok := make(chan bool) cc := &compuCell{ cb: make(map[CallbackHandle]func(int)), } cc.value = f(c.Value()) Register(c, ch, ok) go func() { for range ch { log.Println("got", c.Value()) old := cc.value cc.value = f(c.Value()) if old != cc.value { for _, ch := range cc.observer { log.Println("notify #1") ch.eval <- true <-ch.ok } for _, cb := range cc.cb { log.Println("cb #1") cb(cc.value) } } ok <- true } }() return cc } func (r *react) CreateCompute2(c1, c2 Cell, f func(int, int) int) ComputeCell { ch := make(chan bool) ok := make(chan bool) cc := &compuCell{ cb: make(map[CallbackHandle]func(int)), } cc.value = f(c1.Value(), c2.Value()) Register(c1, ch, ok) Register(c2, ch, ok) go func() { for range ch { old := cc.value cc.value = f(c1.Value(), c2.Value()) if old != cc.value { for _, ch := range cc.observer { log.Println("notify #2") ch.eval <- true <-ch.ok } for _, cb := range cc.cb { log.Println("cb #2") cb(cc.value) } } ok <- true } }() return cc } func (r *react) CreateInput(i int) InputCell { return &inputCell{ cell: cell{value: i}, } } func (c *compuCell) AddCallback(f func(int)) CallbackHandle { c.cb[&f] = f return &f } func (c *compuCell) RemoveCallback(h CallbackHandle) { delete(c.cb, h) } func (c *inputCell) SetValue(i int) { old := c.value c.value = i if old != c.value { for _, ch := range c.observer { log.Println("notify", i) ch.eval <- true <-ch.ok } } } func (c *cell) Value() int { v := c.value log.Println("report", v) return v } func Register(c Cell, ch, ok chan bool) { switch v := c.(type) { case *compuCell: v.observer = append(v.observer, com{ch, ok}) case *inputCell: v.observer = append(v.observer, com{ch, ok}) } }