Official cwtch.im peer and server implementations. https://cwtch.im
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

eventmanager.go 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. package event
  2. import (
  3. "git.openprivacy.ca/openprivacy/libricochet-go/log"
  4. "git.openprivacy.ca/openprivacy/libricochet-go/utils"
  5. "sync"
  6. )
  7. // Event is a structure which binds a given set of data to an Type
  8. type Event struct {
  9. EventType Type
  10. EventID string
  11. Data map[Field]string
  12. }
  13. // NewEvent creates a new event object with a unique ID and the given type and data.
  14. func NewEvent(eventType Type, data map[Field]string) Event {
  15. return Event{EventType: eventType, EventID: utils.GetRandNumber().String(), Data: data}
  16. }
  17. // NewEventList creates a new event object with a unique ID and the given type and data supplied in a list format and composed into a map of Type:string
  18. func NewEventList(eventType Type, args ...interface{}) Event {
  19. data := map[Field]string{}
  20. for i := 0; i < len(args); i += 2 {
  21. key, kok := args[i].(Field)
  22. val, vok := args[i+1].(string)
  23. if kok && vok {
  24. data[key] = val
  25. }
  26. }
  27. return Event{EventType: eventType, EventID: utils.GetRandNumber().String(), Data: data}
  28. }
  29. // Manager is an Event Bus which allows subsystems to subscribe to certain EventTypes and publish others.
  30. type manager struct {
  31. subscribers map[Type][]chan Event
  32. events chan Event
  33. mapMutex sync.Mutex
  34. internal chan bool
  35. closed bool
  36. }
  37. // Manager is an interface for an event bus
  38. type Manager interface {
  39. Subscribe(Type, chan Event)
  40. Publish(Event)
  41. PublishLocal(Event)
  42. Shutdown()
  43. }
  44. // NewEventManager returns an initialized EventManager
  45. func NewEventManager() Manager {
  46. em := &manager{}
  47. em.initialize()
  48. return em
  49. }
  50. // Initialize sets up the Manager.
  51. func (em *manager) initialize() {
  52. em.subscribers = make(map[Type][]chan Event)
  53. em.events = make(chan Event)
  54. em.internal = make(chan bool)
  55. em.closed = false
  56. go em.eventBus()
  57. }
  58. // Subscribe takes an eventType and an Channel and associates them in the eventBus. All future events of that type
  59. // will be sent to the eventChannel.
  60. func (em *manager) Subscribe(eventType Type, eventChannel chan Event) {
  61. em.mapMutex.Lock()
  62. defer em.mapMutex.Unlock()
  63. em.subscribers[eventType] = append(em.subscribers[eventType], eventChannel)
  64. }
  65. // Publish takes an Event and sends it to the internal eventBus where it is distributed to all Subscribers
  66. func (em *manager) Publish(event Event) {
  67. if event.EventType != "" && em.closed != true {
  68. em.events <- event
  69. }
  70. }
  71. // Publish an event only locally, not going over an IPC bridge if there is one
  72. func (em *manager) PublishLocal(event Event) {
  73. em.Publish(event)
  74. }
  75. // eventBus is an internal function that is used to distribute events to all subscribers
  76. func (em *manager) eventBus() {
  77. for {
  78. event := <-em.events
  79. // In the case on an empty event. Teardown the Queue
  80. if event.EventType == "" {
  81. break
  82. }
  83. // maps aren't thread safe
  84. em.mapMutex.Lock()
  85. subscribers := em.subscribers[event.EventType]
  86. em.mapMutex.Unlock()
  87. // Send the event to any subscribers to that event type
  88. for _, subscriber := range subscribers {
  89. select {
  90. case subscriber <- event:
  91. log.Debugf("Sending %v to %v", event.EventType, subscriber)
  92. default:
  93. log.Errorf("Failed to send %v to %v. The subsystem might be running too slow!", event.EventType, subscriber)
  94. }
  95. }
  96. }
  97. // We are about to exit the eventbus thread, fire off an event internally
  98. em.internal <- true
  99. }
  100. // Shutdown triggers, and waits for, the internal eventBus goroutine to finish
  101. func (em *manager) Shutdown() {
  102. em.events <- Event{}
  103. em.closed = true
  104. // wait for eventBus to finish
  105. <-em.internal
  106. close(em.events)
  107. close(em.internal)
  108. }