gobot.io/x/gobot@v1.16.0/eventer.go (about) 1 package gobot 2 3 import "sync" 4 5 type eventChannel chan *Event 6 7 type eventer struct { 8 // map of valid Event names 9 eventnames map[string]string 10 11 // new events get put in to the event channel 12 in eventChannel 13 14 // map of out channels used by subscribers 15 outs map[eventChannel]eventChannel 16 17 // mutex to protect the eventChannel map 18 eventsMutex sync.Mutex 19 } 20 21 const eventChanBufferSize = 10 22 23 // Eventer is the interface which describes how a Driver or Adaptor 24 // handles events. 25 type Eventer interface { 26 // Events returns the map of valid Event names. 27 Events() (eventnames map[string]string) 28 29 // Event returns an Event string from map of valid Event names. 30 // Mostly used to validate that an Event name is valid. 31 Event(name string) string 32 33 // AddEvent registers a new Event name. 34 AddEvent(name string) 35 36 // DeleteEvent removes a previously registered Event name. 37 DeleteEvent(name string) 38 39 // Publish new events to any subscriber 40 Publish(name string, data interface{}) 41 42 // Subscribe to events 43 Subscribe() (events eventChannel) 44 45 // Unsubscribe from an event channel 46 Unsubscribe(events eventChannel) 47 48 // Event handler 49 On(name string, f func(s interface{})) (err error) 50 51 // Event handler, only executes one time 52 Once(name string, f func(s interface{})) (err error) 53 } 54 55 // NewEventer returns a new Eventer. 56 func NewEventer() Eventer { 57 evtr := &eventer{ 58 eventnames: make(map[string]string), 59 in: make(eventChannel, eventChanBufferSize), 60 outs: make(map[eventChannel]eventChannel), 61 } 62 63 // goroutine to cascade "in" events to all "out" event channels 64 go func() { 65 for { 66 select { 67 case evt := <-evtr.in: 68 evtr.eventsMutex.Lock() 69 for _, out := range evtr.outs { 70 out <- evt 71 } 72 evtr.eventsMutex.Unlock() 73 } 74 } 75 }() 76 77 return evtr 78 } 79 80 // Events returns the map of valid Event names. 81 func (e *eventer) Events() map[string]string { 82 return e.eventnames 83 } 84 85 // Event returns an Event string from map of valid Event names. 86 // Mostly used to validate that an Event name is valid. 87 func (e *eventer) Event(name string) string { 88 return e.eventnames[name] 89 } 90 91 // AddEvent registers a new Event name. 92 func (e *eventer) AddEvent(name string) { 93 e.eventnames[name] = name 94 } 95 96 // DeleteEvent removes a previously registered Event name. 97 func (e *eventer) DeleteEvent(name string) { 98 delete(e.eventnames, name) 99 } 100 101 // Publish new events to anyone that is subscribed 102 func (e *eventer) Publish(name string, data interface{}) { 103 evt := NewEvent(name, data) 104 e.in <- evt 105 } 106 107 // Subscribe to any events from this eventer 108 func (e *eventer) Subscribe() eventChannel { 109 e.eventsMutex.Lock() 110 defer e.eventsMutex.Unlock() 111 out := make(eventChannel, eventChanBufferSize) 112 e.outs[out] = out 113 return out 114 } 115 116 // Unsubscribe from the event channel 117 func (e *eventer) Unsubscribe(events eventChannel) { 118 e.eventsMutex.Lock() 119 defer e.eventsMutex.Unlock() 120 delete(e.outs, events) 121 } 122 123 // On executes the event handler f when e is Published to. 124 func (e *eventer) On(n string, f func(s interface{})) (err error) { 125 out := e.Subscribe() 126 go func() { 127 for { 128 select { 129 case evt := <-out: 130 if evt.Name == n { 131 f(evt.Data) 132 } 133 } 134 } 135 }() 136 137 return 138 } 139 140 // Once is similar to On except that it only executes f one time. 141 func (e *eventer) Once(n string, f func(s interface{})) (err error) { 142 out := e.Subscribe() 143 go func() { 144 ProcessEvents: 145 for evt := range out { 146 if evt.Name == n { 147 f(evt.Data) 148 e.Unsubscribe(out) 149 break ProcessEvents 150 } 151 } 152 }() 153 154 return 155 }