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}) } }