gobot.io/x/gobot/v2@v2.1.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 evt := <-evtr.in 67 evtr.eventsMutex.Lock() 68 for _, out := range evtr.outs { 69 out <- evt 70 } 71 evtr.eventsMutex.Unlock() 72 } 73 }() 74 75 return evtr 76 } 77 78 // Events returns the map of valid Event names. 79 func (e *eventer) Events() map[string]string { 80 return e.eventnames 81 } 82 83 // Event returns an Event string from map of valid Event names. 84 // Mostly used to validate that an Event name is valid. 85 func (e *eventer) Event(name string) string { 86 return e.eventnames[name] 87 } 88 89 // AddEvent registers a new Event name. 90 func (e *eventer) AddEvent(name string) { 91 e.eventnames[name] = name 92 } 93 94 // DeleteEvent removes a previously registered Event name. 95 func (e *eventer) DeleteEvent(name string) { 96 delete(e.eventnames, name) 97 } 98 99 // Publish new events to anyone that is subscribed 100 func (e *eventer) Publish(name string, data interface{}) { 101 evt := NewEvent(name, data) 102 e.in <- evt 103 } 104 105 // Subscribe to any events from this eventer 106 func (e *eventer) Subscribe() eventChannel { 107 e.eventsMutex.Lock() 108 defer e.eventsMutex.Unlock() 109 out := make(eventChannel, eventChanBufferSize) 110 e.outs[out] = out 111 return out 112 } 113 114 // Unsubscribe from the event channel 115 func (e *eventer) Unsubscribe(events eventChannel) { 116 e.eventsMutex.Lock() 117 defer e.eventsMutex.Unlock() 118 delete(e.outs, events) 119 } 120 121 // On executes the event handler f when e is Published to. 122 func (e *eventer) On(n string, f func(s interface{})) (err error) { 123 out := e.Subscribe() 124 go func() { 125 for { 126 evt := <-out 127 if evt.Name == n { 128 f(evt.Data) 129 } 130 } 131 }() 132 133 return 134 } 135 136 // Once is similar to On except that it only executes f one time. 137 func (e *eventer) Once(n string, f func(s interface{})) (err error) { 138 out := e.Subscribe() 139 go func() { 140 ProcessEvents: 141 for evt := range out { 142 if evt.Name == n { 143 f(evt.Data) 144 e.Unsubscribe(out) 145 break ProcessEvents 146 } 147 } 148 }() 149 150 return 151 }