summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2016-08-29 13:55:15 +0200
committerDimitri Sokolyuk <demon@dim13.org>2016-08-29 13:55:15 +0200
commitcfbbac64e432e37e1a17ab1b01d5a2da08ca38d7 (patch)
tree7b1c0f517d1cbbbc0c5cc5ceab246ab0911857ef
parent13444d068d2428fd2592420591a7a5f2432350e0 (diff)
Semi-ok
-rw-r--r--go/react/react.go96
1 files changed, 82 insertions, 14 deletions
diff --git a/go/react/react.go b/go/react/react.go
index 1f93906..069d7be 100644
--- a/go/react/react.go
+++ b/go/react/react.go
@@ -1,5 +1,7 @@
package react
+import "log"
+
const testVersion = 4
type react struct {
@@ -9,17 +11,18 @@ type inputCell struct {
cell
}
-type computeCell struct {
+type compuCell struct {
cell
cb map[CallbackHandle]func(int)
}
-func newComputeCell() *computeCell {
- return &computeCell{cb: make(map[CallbackHandle]func(int))}
+type com struct {
+ eval, ok chan bool
}
type cell struct {
- value int
+ value int
+ observer []com
}
func New() Reactor {
@@ -27,17 +30,63 @@ func New() Reactor {
}
func (r *react) CreateCompute1(c Cell, f func(int) int) ComputeCell {
- return &computeCell{
- cell: cell{value: f(c.Value())},
- cb: make(map[CallbackHandle]func(int)),
+ 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 {
- return &computeCell{
- cell: cell{value: f(c1.Value(), c2.Value())},
- cb: make(map[CallbackHandle]func(int)),
+ 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 {
@@ -46,19 +95,38 @@ func (r *react) CreateInput(i int) InputCell {
}
}
-func (c *computeCell) AddCallback(f func(int)) CallbackHandle {
+func (c *compuCell) AddCallback(f func(int)) CallbackHandle {
c.cb[&f] = f
return &f
}
-func (c *computeCell) RemoveCallback(h CallbackHandle) {
+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 {
- return c.value
+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})
+ }
}