dispatcher.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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. import ()
  6. type Dispatcher struct {
  7. evmap map[string][]subscription // maps event name to subcriptions list
  8. cancel bool // flag informing cancelled dispatch
  9. }
  10. type IDispatcher interface {
  11. Subscribe(evname string, cb Callback)
  12. SubscribeID(evname string, id interface{}, cb Callback)
  13. UnsubscribeID(evname string, id interface{}) int
  14. Dispatch(evname string, ev interface{}) bool
  15. ClearSubscriptions()
  16. CancelDispatch()
  17. }
  18. type Callback func(string, interface{})
  19. type subscription struct {
  20. id interface{}
  21. cb func(string, interface{})
  22. }
  23. // NewEventDispatcher creates and returns a pointer to an Event Dispatcher
  24. func NewDispatcher() *Dispatcher {
  25. ed := new(Dispatcher)
  26. ed.Initialize()
  27. return ed
  28. }
  29. // Initialize initializes this event dispatcher.
  30. // It is normally used by other types which embed an event dispatcher
  31. func (ed *Dispatcher) Initialize() {
  32. ed.evmap = make(map[string][]subscription)
  33. }
  34. // Subscribe subscribes to receive events with the given name.
  35. // If it is necessary to unsubscribe the event, the function SubscribeID
  36. // should be used.
  37. func (ed *Dispatcher) Subscribe(evname string, cb Callback) {
  38. ed.SubscribeID(evname, nil, cb)
  39. }
  40. // Subscribe subscribes to receive events with the given name.
  41. // The function accepts a unique id to be use to unsubscribe this event
  42. func (ed *Dispatcher) SubscribeID(evname string, id interface{}, cb Callback) {
  43. //log.Debug("Dispatcher(%p).SubscribeID:%s (%v)", ed, evname, id)
  44. ed.evmap[evname] = append(ed.evmap[evname], subscription{id, cb})
  45. }
  46. // Unsubscribe unsubscribes from the specified event and subscription id
  47. // Returns the number of subscriptions found.
  48. func (ed *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 := ed.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. //log.Debug("Dispatcher(%p).UnsubscribeID:%s (%p): %v",ed, evname, id, found)
  69. ed.evmap[evname] = subs
  70. return found
  71. }
  72. // Dispatch dispatch the specified event and data to all registered subscribers.
  73. // The function returns true if the propagation was cancelled by a subscriber.
  74. func (ed *Dispatcher) Dispatch(evname string, ev interface{}) bool {
  75. // Get list of subscribers for this event
  76. subs := ed.evmap[evname]
  77. if subs == nil {
  78. return false
  79. }
  80. // Dispatch to all subscribers
  81. //log.Debug("Dispatcher(%p).Dispatch:%s", ed, evname)
  82. ed.cancel = false
  83. for i := 0; i < len(subs); i++ {
  84. subs[i].cb(evname, ev)
  85. if ed.cancel {
  86. break
  87. }
  88. }
  89. return ed.cancel
  90. }
  91. // ClearSubscriptions clear all subscriptions from this dispatcher
  92. func (ed *Dispatcher) ClearSubscriptions() {
  93. ed.evmap = make(map[string][]subscription)
  94. //log.Debug("Dispatcher(%p).ClearSubscriptions: %d", ed, len(ed.evmap))
  95. }
  96. // CancelDispatch cancels the propagation of the current event.
  97. // No more subscribers will be called for this event dispatch.
  98. func (ed *Dispatcher) CancelDispatch() {
  99. ed.cancel = true
  100. }
  101. //// LogSubscriptions is used for debugging to log the current
  102. //// subscriptions of this dispatcher
  103. //func (ed *Dispatcher) LogSubscriptions() {
  104. //
  105. // for evname, subs := range ed.evmap {
  106. // log.Debug("event:%s", evname)
  107. // for _, sub := range subs {
  108. // log.Debug(" subscription:%v", sub)
  109. // }
  110. // }
  111. // log.Debug("")
  112. //}