""" Dispatch Events to registered handlers. Author: Georg Hopp """ import sys import time import threading from collections import deque from Event import Event from EventHandler import EventHandler from EventSubject import EventSubject class DefaultHandler(EventHandler): def handleEvent(self, event): return True SERVER = 0x00 CLIENT = 0x01 class EventDispatcher(EventSubject): _EVENTS = { 'heartbeat' : 0x01, 'user_wait' : 0x02, 'data_wait' : 0x03, 'shutdown' : 0x04 } def __init__(self, mode = SERVER, default_handler = DefaultHandler()): super(EventDispatcher, self).__init__() self._events = deque([]) self._handler = {} self._default_handler = default_handler self._running = False self._heartbeat = 0.0 self._nextbeat = 0.0 self._mode = mode self._queue_lock = threading.Lock() self._event_wait = threading.Condition() self._data_wait_id = EventDispatcher.eventId('data_wait') self._user_wait_id = EventDispatcher.eventId('user_wait') def registerHandler(self, handler): for eid in handler.getHandledIds(): if eid in self._handler: self._handler[eid].append(handler) else: self._handler[eid] = [handler] handler.setDispatcher(self) def setHeartbeat(self, heartbeat): self._heartbeat = heartbeat if self._heartbeat: self._nextbeat = time.time() + self._heartbeat else: self._nextbeat = 0.0 def getBeattime(self): return self._nextbeat - time.time() def getDataWaitTime(self): if self._mode == SERVER: return self.getBeattime() # here comes a timeout into play.... currently I expect # the stuff to work... # TODO add timeout return 0.0 def queueEvent(self, event): self._queue_lock.acquire() self._events.append(event) self._queue_lock.release() self._event_wait.acquire() self._event_wait.notify_all() self._event_wait.release() def start(self, name): self._running = True while self._running or self._events: now = time.time() if self._nextbeat and self._nextbeat <= now: self._nextbeat += self._heartbeat self.queueEvent(self.emit('heartbeat')) current = None if not self._events: if not name: if self._mode == CLIENT: current = self.emit('user_wait') else: current = self.emit('data_wait') else: self._event_wait.acquire() self._event_wait.wait() self._event_wait.release() self._queue_lock.acquire() if (not current) and self._events: current = self._events.popleft() self._queue_lock.release() if current: if current.type not in self._handler: #print '[%s] handle: %s(%d) on %s: %s' % ( # name, current.name, current.sno, hex(id(current.subject)), 'default') self._default_handler.handleEvent(current) else: for handler in self._handler[current.type]: #print '[%s] handle: %s(%d) on %s: %s' % ( # name, current.name, current.sno, hex(id(current.subject)), # handler.__class__.__name__) if handler.handleEvent(current): break # if we leave the loop eventually inform all other threads # so they can quit too. self._event_wait.acquire() self._event_wait.notify_all() self._event_wait.release() def stop(self): self._running = False def shutdown(self): self.queueEvent(self.emit('shutdown')) self.stop() # vim: set ft=python et ts=8 sw=4 sts=4: