dispatcher.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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. // Dispatcher implements an event dispatcher
  6. type Dispatcher struct {
  7. evmap map[string][]subscription // maps event name to subcriptions list
  8. cancel bool // flag informing cancelled dispatch
  9. }
  10. // IDispatcher is the interface for dispatchers
  11. type IDispatcher interface {
  12. Subscribe(evname string, cb Callback)
  13. SubscribeID(evname string, id interface{}, cb Callback)
  14. UnsubscribeID(evname string, id interface{}) int
  15. Dispatch(evname string, ev interface{}) bool
  16. ClearSubscriptions()
  17. CancelDispatch()
  18. }
  19. // Callback is the type for the Dispatcher callbacks functions
  20. type Callback func(string, interface{})
  21. type subscription struct {
  22. id interface{}
  23. cb func(string, interface{})
  24. }
  25. // NewDispatcher creates and returns a new Event Dispatcher
  26. func NewDispatcher() *Dispatcher {
  27. d := new(Dispatcher)
  28. d.Initialize()
  29. return d
  30. }
  31. // Initialize initializes this event dispatcher.
  32. // It is normally used by other types which embed an event dispatcher
  33. func (d *Dispatcher) Initialize() {
  34. d.evmap = make(map[string][]subscription)
  35. }
  36. // Subscribe subscribes to receive events with the given name.
  37. // If it is necessary to unsubscribe the event, the function SubscribeID should be used.
  38. func (d *Dispatcher) Subscribe(evname string, cb Callback) {
  39. d.SubscribeID(evname, nil, cb)
  40. }
  41. // SubscribeID subscribes to receive events with the given name.
  42. // The function accepts a unique id to be use to unsubscribe this event
  43. func (d *Dispatcher) SubscribeID(evname string, id interface{}, cb Callback) {
  44. d.evmap[evname] = append(d.evmap[evname], subscription{id, cb})
  45. }
  46. // UnsubscribeID unsubscribes from the specified event and subscription id
  47. // Returns the number of subscriptions found.
  48. func (d *Dispatcher) UnsubscribeID(evname string, id interface{}) int {
  49. // Get list of subscribers for this event
  50. // If not found, nothing to do
  51. subs, ok := d.evmap[evname]
  52. if !ok {
  53. return 0
  54. }
  55. // Remove all subscribers with the specified id for this event
  56. found := 0
  57. pos := 0
  58. for pos < len(subs) {
  59. if subs[pos].id == id {
  60. copy(subs[pos:], subs[pos+1:])
  61. subs[len(subs)-1] = subscription{}
  62. subs = subs[:len(subs)-1]
  63. found++
  64. } else {
  65. pos++
  66. }
  67. }
  68. d.evmap[evname] = subs
  69. return found
  70. }
  71. // UnsubscribeAllID unsubscribes from all events with the specified subscription id.
  72. // Returns the number of subscriptions found.
  73. func (d *Dispatcher) UnsubscribeAllID(id interface{}) int {
  74. total := 0
  75. for evname := range d.evmap {
  76. found := d.UnsubscribeID(evname, id)
  77. total += found
  78. }
  79. return total
  80. }
  81. // Dispatch dispatch the specified event and data to all registered subscribers.
  82. // The function returns true if the propagation was cancelled by a subscriber.
  83. func (d *Dispatcher) Dispatch(evname string, ev interface{}) bool {
  84. // Get list of subscribers for this event
  85. subs := d.evmap[evname]
  86. if subs == nil {
  87. return false
  88. }
  89. // Dispatch to all subscribers
  90. d.cancel = false
  91. for i := 0; i < len(subs); i++ {
  92. subs[i].cb(evname, ev)
  93. if d.cancel {
  94. break
  95. }
  96. }
  97. return d.cancel
  98. }
  99. // ClearSubscriptions clear all subscriptions from this dispatcher
  100. func (d *Dispatcher) ClearSubscriptions() {
  101. d.evmap = make(map[string][]subscription)
  102. }
  103. // CancelDispatch cancels the propagation of the current event.
  104. // No more subscribers will be called for this event dispatch.
  105. func (d *Dispatcher) CancelDispatch() {
  106. d.cancel = true
  107. }