aboutsummaryrefslogtreecommitdiffstats
path: root/ethutil/reactor.go
diff options
context:
space:
mode:
Diffstat (limited to 'ethutil/reactor.go')
-rw-r--r--ethutil/reactor.go87
1 files changed, 87 insertions, 0 deletions
diff --git a/ethutil/reactor.go b/ethutil/reactor.go
new file mode 100644
index 000000000..7cf145245
--- /dev/null
+++ b/ethutil/reactor.go
@@ -0,0 +1,87 @@
+package ethutil
+
+import (
+ "sync"
+)
+
+type ReactorEvent struct {
+ mut sync.Mutex
+ event string
+ chans []chan React
+}
+
+// Post the specified reactor resource on the channels
+// currently subscribed
+func (e *ReactorEvent) Post(react React) {
+ e.mut.Lock()
+ defer e.mut.Unlock()
+
+ for _, ch := range e.chans {
+ go func(ch chan React) {
+ ch <- react
+ }(ch)
+ }
+}
+
+// Add a subscriber to this event
+func (e *ReactorEvent) Add(ch chan React) {
+ e.mut.Lock()
+ defer e.mut.Unlock()
+
+ e.chans = append(e.chans, ch)
+}
+
+// Remove a subscriber
+func (e *ReactorEvent) Remove(ch chan React) {
+ e.mut.Lock()
+ defer e.mut.Unlock()
+
+ for i, c := range e.chans {
+ if c == ch {
+ e.chans = append(e.chans[:i], e.chans[i+1:]...)
+ }
+ }
+}
+
+// Basic reactor resource
+type React struct {
+ Resource interface{}
+ Event string
+}
+
+// The reactor basic engine. Acts as bridge
+// between the events and the subscribers/posters
+type ReactorEngine struct {
+ patterns map[string]*ReactorEvent
+}
+
+func NewReactorEngine() *ReactorEngine {
+ return &ReactorEngine{patterns: make(map[string]*ReactorEvent)}
+}
+
+// Subscribe a channel to the specified event
+func (reactor *ReactorEngine) Subscribe(event string, ch chan React) {
+ ev := reactor.patterns[event]
+ // Create a new event if one isn't available
+ if ev == nil {
+ ev = &ReactorEvent{event: event}
+ reactor.patterns[event] = ev
+ }
+
+ // Add the channel to reactor event handler
+ ev.Add(ch)
+}
+
+func (reactor *ReactorEngine) Unsubscribe(event string, ch chan React) {
+ ev := reactor.patterns[event]
+ if ev != nil {
+ ev.Remove(ch)
+ }
+}
+
+func (reactor *ReactorEngine) Post(event string, resource interface{}) {
+ ev := reactor.patterns[event]
+ if ev != nil {
+ ev.Post(React{Resource: resource, Event: event})
+ }
+}