62 lines
1.5 KiB
Python
62 lines
1.5 KiB
Python
import logging
|
|
import time
|
|
from collections import defaultdict
|
|
from itertools import chain
|
|
from threading import Thread, RLock
|
|
|
|
ALL_EVENTS = '*'
|
|
|
|
class EventBus:
|
|
def __init__(self):
|
|
self.listeners = defaultdict(list)
|
|
self.lock = RLock()
|
|
self.logger =logging.getLogger("EventBus")
|
|
|
|
def fire(self, event):
|
|
assert isinstance(event, Event), "event needs to be an instance of Event"
|
|
|
|
# We dont want the eventbus to be blocking, run in a thread
|
|
def run():
|
|
self.lock.acquire()
|
|
|
|
self.logger.info("[{}] {} event received: {}".format(time.strftime("%H:%M:%S"), event.eventType, event.data))
|
|
|
|
for callback in chain(self.listeners[ALL_EVENTS], self.listeners[event.eventType]):
|
|
callback(event)
|
|
|
|
if event.removeListener:
|
|
if callback in self.listeners[ALL_EVENTS]:
|
|
self.listeners[ALL_EVENTS].remove(callback)
|
|
|
|
if callback in self.listeners[event.eventType]:
|
|
self.listeners[event.eventType].remove(callback)
|
|
|
|
event.removeListener = False
|
|
|
|
if event.stopPropegating:
|
|
break
|
|
|
|
self.lock.release()
|
|
|
|
Thread(target=run).start()
|
|
|
|
def listen(self, event_type, callback):
|
|
self.lock.acquire()
|
|
|
|
self.listeners[event_type].append(callback)
|
|
|
|
self.logger.info("New listener added for event {}. Total: {}".format(event_type, len(self.listeners[event_type])))
|
|
|
|
self.lock.release()
|
|
|
|
|
|
class Event:
|
|
def __init__(self, eventType, data):
|
|
self.eventType = eventType
|
|
self.data = data
|
|
self.stopPropegating = False
|
|
self.removeListener = False
|
|
|
|
def __str__(self):
|
|
return str([self.eventType, self.data])
|
|
|