aboutsummaryrefslogblamecommitdiffstats
path: root/eventer/eventer.go
blob: 6e5ee2ec57c54b6316048761554f36a57f32b43a (plain) (tree)
1
2
3
4

               

             


























                                     
                             



                          
                                                      


                                                       
                      
                                                          
                        

























                                                                  



                                                              
                       






                                                                                     
                         
 
package eventer

import "sync"

// Basic receiver interface.
type Receiver interface {
    Send(Event)
}

// Receiver as channel
type Channel chan Event

func (self Channel) Send(ev Event) {
    self <- ev
}

// Receiver as function
type Function func(ev Event)

func (self Function) Send(ev Event) {
    self(ev)
}

type Event struct {
    Type string
    Data interface{}
}

type Channels map[string][]Receiver

type EventMachine struct {
    mu       sync.RWMutex
    channels Channels
}

func New() *EventMachine {
    return &EventMachine{channels: make(Channels)}
}

func (self *EventMachine) add(typ string, r Receiver) {
    self.mu.Lock()
    self.channels[typ] = append(self.channels[typ], r)
    self.mu.Unlock()
}

// Generalised methods for the known receiver types
// * Channel
// * Function
func (self *EventMachine) On(typ string, r interface{}) {
    if eventFunc, ok := r.(func(Event)); ok {
        self.RegisterFunc(typ, eventFunc)
    } else if eventChan, ok := r.(Channel); ok {
        self.RegisterChannel(typ, eventChan)
    } else {
        panic("Invalid type for EventMachine::On")
    }
}

func (self *EventMachine) RegisterChannel(typ string, c Channel) {
    self.add(typ, c)
}

func (self *EventMachine) RegisterFunc(typ string, f Function) {
    self.add(typ, f)
}

func (self *EventMachine) Register(typ string) Channel {
    c := make(Channel, 1)
    self.add(typ, c)
    return c
}

func (self *EventMachine) Post(typ string, data interface{}) {
    self.mu.RLock()
    if self.channels[typ] != nil {
        ev := Event{typ, data}
        for _, receiver := range self.channels[typ] {
            // Blocking is OK. These are internals and need to be handled
            receiver.Send(ev)
        }
    }
    self.mu.RUnlock()
}