dispatcher.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. // Copyright 2016 The G3N Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package core
  5. // IDispatcher is the interface for event dispatchers.
  6. type IDispatcher interface {
  7. Subscribe(evname string, cb Callback)
  8. SubscribeID(evname string, id interface{}, cb Callback)
  9. UnsubscribeID(evname string, id interface{}) int
  10. UnsubscribeAllID(id interface{}) int
  11. Dispatch(evname string, ev interface{}) int
  12. }
  13. // Dispatcher implements an event dispatcher.
  14. type Dispatcher struct {
  15. evmap map[string][]subscription // Map of event names to subscription lists
  16. }
  17. // Callback is the type for Dispatcher callback functions.
  18. type Callback func(string, interface{})
  19. // subscription links a Callback with a user-provided unique id.
  20. type subscription struct {
  21. id interface{}
  22. cb Callback
  23. }
  24. // NewDispatcher creates and returns a new event dispatcher.
  25. func NewDispatcher() *Dispatcher {
  26. d := new(Dispatcher)
  27. d.Initialize()
  28. return d
  29. }
  30. // Initialize initializes the event dispatcher.
  31. // It is normally used by other types which embed a dispatcher.
  32. func (d *Dispatcher) Initialize() {
  33. d.evmap = make(map[string][]subscription)
  34. }
  35. // Subscribe subscribes a callback to events with the given name.
  36. // If it is necessary to unsubscribe later, SubscribeID should be used instead.
  37. func (d *Dispatcher) Subscribe(evname string, cb Callback) {
  38. d.evmap[evname] = append(d.evmap[evname], subscription{nil, cb})
  39. }
  40. // SubscribeID subscribes a callback to events events with the given name.
  41. // The user-provided unique id can be used to unsubscribe via UnsubscribeID.
  42. func (d *Dispatcher) SubscribeID(evname string, id interface{}, cb Callback) {
  43. d.evmap[evname] = append(d.evmap[evname], subscription{id, cb})
  44. }
  45. // UnsubscribeID removes all subscribed callbacks with the specified unique id from the specified event.
  46. // Returns the number of subscriptions removed.
  47. func (d *Dispatcher) UnsubscribeID(evname string, id interface{}) int {
  48. // Get list of subscribers for this event
  49. subs := d.evmap[evname]
  50. if len(subs) == 0 {
  51. return 0
  52. }
  53. // Remove all subscribers of the specified event with the specified id, counting how many were removed
  54. rm := 0
  55. i := 0
  56. for _, s := range subs {
  57. if s.id == id {
  58. rm++
  59. } else {
  60. subs[i] = s
  61. i++
  62. }
  63. }
  64. d.evmap[evname] = subs[:i]
  65. return rm
  66. }
  67. // UnsubscribeAllID removes all subscribed callbacks with the specified unique id from all events.
  68. // Returns the number of subscriptions removed.
  69. func (d *Dispatcher) UnsubscribeAllID(id interface{}) int {
  70. // Remove all subscribers with the specified id (for all events), counting how many were removed
  71. total := 0
  72. for evname := range d.evmap {
  73. total += d.UnsubscribeID(evname, id)
  74. }
  75. return total
  76. }
  77. // Dispatch dispatches the specified event to all registered subscribers.
  78. // The function returns the number of subscribers to which the event was dispatched.
  79. func (d *Dispatcher) Dispatch(evname string, ev interface{}) int {
  80. // Get list of subscribers for this event
  81. subs := d.evmap[evname]
  82. nsubs := len(subs)
  83. if nsubs == 0 {
  84. return 0
  85. }
  86. // Dispatch event to all subscribers
  87. for _, s := range subs {
  88. s.cb(evname, ev)
  89. }
  90. return nsubs
  91. }