| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- // Copyright 2016 The G3N Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package core
- // Dispatcher implements an event dispatcher
- type Dispatcher struct {
- evmap map[string][]subscription // maps event name to subcriptions list
- cancel bool // flag informing cancelled dispatch
- }
- // IDispatcher is the interface for dispatchers
- type IDispatcher interface {
- Subscribe(evname string, cb Callback)
- SubscribeID(evname string, id interface{}, cb Callback)
- UnsubscribeID(evname string, id interface{}) int
- Dispatch(evname string, ev interface{}) bool
- ClearSubscriptions()
- CancelDispatch()
- }
- // Callback is the type for the Dispatcher callbacks functions
- type Callback func(string, interface{})
- type subscription struct {
- id interface{}
- cb func(string, interface{})
- }
- // NewDispatcher creates and returns a new Event Dispatcher
- func NewDispatcher() *Dispatcher {
- d := new(Dispatcher)
- d.Initialize()
- return d
- }
- // Initialize initializes this event dispatcher.
- // It is normally used by other types which embed an event dispatcher
- func (d *Dispatcher) Initialize() {
- d.evmap = make(map[string][]subscription)
- }
- // Subscribe subscribes to receive events with the given name.
- // If it is necessary to unsubscribe the event, the function SubscribeID should be used.
- func (d *Dispatcher) Subscribe(evname string, cb Callback) {
- d.SubscribeID(evname, nil, cb)
- }
- // SubscribeID subscribes to receive events with the given name.
- // The function accepts a unique id to be use to unsubscribe this event
- func (d *Dispatcher) SubscribeID(evname string, id interface{}, cb Callback) {
- d.evmap[evname] = append(d.evmap[evname], subscription{id, cb})
- }
- // UnsubscribeID unsubscribes from the specified event and subscription id
- // Returns the number of subscriptions found.
- func (d *Dispatcher) UnsubscribeID(evname string, id interface{}) int {
- // Get list of subscribers for this event
- // If not found, nothing to do
- subs, ok := d.evmap[evname]
- if !ok {
- return 0
- }
- // Remove all subscribers with the specified id for this event
- found := 0
- pos := 0
- for pos < len(subs) {
- if subs[pos].id == id {
- copy(subs[pos:], subs[pos+1:])
- subs[len(subs)-1] = subscription{}
- subs = subs[:len(subs)-1]
- found++
- } else {
- pos++
- }
- }
- d.evmap[evname] = subs
- return found
- }
- // UnsubscribeAllID unsubscribes from all events with the specified subscription id.
- // Returns the number of subscriptions found.
- func (d *Dispatcher) UnsubscribeAllID(id interface{}) int {
- total := 0
- for evname := range d.evmap {
- found := d.UnsubscribeID(evname, id)
- total += found
- }
- return total
- }
- // Dispatch dispatch the specified event and data to all registered subscribers.
- // The function returns true if the propagation was cancelled by a subscriber.
- func (d *Dispatcher) Dispatch(evname string, ev interface{}) bool {
- // Get list of subscribers for this event
- subs := d.evmap[evname]
- if subs == nil {
- return false
- }
- // Dispatch to all subscribers
- d.cancel = false
- for i := 0; i < len(subs); i++ {
- subs[i].cb(evname, ev)
- if d.cancel {
- break
- }
- }
- return d.cancel
- }
- // ClearSubscriptions clear all subscriptions from this dispatcher
- func (d *Dispatcher) ClearSubscriptions() {
- d.evmap = make(map[string][]subscription)
- }
- // CancelDispatch cancels the propagation of the current event.
- // No more subscribers will be called for this event dispatch.
- func (d *Dispatcher) CancelDispatch() {
- d.cancel = true
- }
|