summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorIsaku Yamahata <yamahata@valinux.co.jp>2012-01-31 16:45:03 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2012-02-01 08:55:40 +0900
commit58658d3ed4eefd3f9fdc289d629acce9c830eab6 (patch)
treee5cc062793f846709b76fd135f1aa237e78fc038
parentf9bae8bb898dce7816f84fed196a49f9a03ed52a (diff)
dispacher: introduce inheritable handler
Introduce inheritable handler which inherits during dispatcher change for convenience. Thus, we don't have to watch dispatcher change event and unregister/register. Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r--ryu/controller/dispatcher.py62
1 files changed, 39 insertions, 23 deletions
diff --git a/ryu/controller/dispatcher.py b/ryu/controller/dispatcher.py
index 629d6a15..7b0f02aa 100644
--- a/ryu/controller/dispatcher.py
+++ b/ryu/controller/dispatcher.py
@@ -68,7 +68,7 @@ class EventQueue(object):
def set_dispatcher(self, dispatcher):
old = self.dispatcher
- new = dispatcher.clone()
+ new = dispatcher.clone(old)
self.dispatcher = new
self._queue_q_ev(EventDispatcherChange(self, old, new))
@@ -113,16 +113,22 @@ class EventDispatcher(object):
self.children = weakref.WeakSet()
self.name = name
self.events = {}
+ self.inheritable_events = {}
self.all_handlers = []
self.event_dispatchers.add(self)
- def clone(self):
+ def clone(self, old_dispatcher=None):
cloned = EventDispatcher(self.name)
for ev_cls, h in self.events.items():
cloned.events[ev_cls] = copy.copy(h)
cloned.all_handlers = copy.copy(self.all_handlers)
self.children.add(cloned)
+
+ if old_dispatcher is not None:
+ cloned.inheritable_events = old_dispatcher.inheritable_events
+ old_dispatcher.inheritable_events = {}
+
return cloned
def _foreach_children(self, call, *args, **kwargs):
@@ -130,6 +136,7 @@ class EventDispatcher(object):
call(c, *args, **kwargs)
def register_all_handler(self, all_handler):
+ assert callable(all_handler)
self.all_handlers.append(all_handler)
self._foreach_children(EventDispatcher.register_all_handler,
all_handler)
@@ -137,7 +144,15 @@ class EventDispatcher(object):
def unregister_all_handler(self, all_handler):
self._foreach_children(EventDispatcher.unregister_all_handler,
all_handler)
- del self.all_handlers[all_handler]
+ self.all_handlers.remove(all_handler)
+
+ def register_inheritable_handler(self, ev_cls, inheritable_handler):
+ assert callable(inheritable_handler)
+ self.inheritable_events.setdefault(ev_cls, [])
+ self.inheritable_events[ev_cls].append(inheritable_handler)
+
+ def unregister_inheritable_handler(self, ev_cls, inheritable_handler):
+ self.inheritable_events[ev_cls].remove(inheritable_handler)
def register_handler(self, ev_cls, handler):
assert callable(handler)
@@ -153,7 +168,7 @@ class EventDispatcher(object):
def unregister_handler(self, ev_cls, handler):
self._foreach_children(EventDispatcher.unregister_handler,
ev_cls, handler)
- del self.events[ev_cls][handler]
+ self.events[ev_cls].remove(handler)
def register_static(self, ev_cls):
'''helper decorator to statically register handler for event class'''
@@ -169,35 +184,36 @@ class EventDispatcher(object):
def __call__(self, ev):
self.dispatch(ev)
- def dispatch(self, ev):
- #LOG.debug('dispatch %s', ev)
+ @staticmethod
+ def _dispatch(ev, handlers):
+ if len(handlers) == 0:
+ return False
# copy handler list because the list is not stable.
# event handler may block/switch thread execution
- # and un/register other handlers. And more,
+ # and un/register other handlers.
# handler itself may un/register handlers.
- all_handlers = copy.copy(self.all_handlers)
- for h in all_handlers:
+ handlers = copy.copy(handlers)
+ for h in handlers:
ret = h(ev)
if ret is False:
break
+ return True
- if ev.__class__ not in self.events:
- LOG.info('unhandled event %s', ev)
- return
+ def dispatch(self, ev):
+ #LOG.debug('dispatch %s', ev)
+ handled = False
- # Is this necessary?
- #
- # copy handler list because the list is not stable.
- # event handler may block/switch thread execution
- # and un/register other handlers.
- #
- handlers = copy.copy(self.events[ev.__class__])
+ self._dispatch(ev, self.all_handlers)
- for h in handlers:
- ret = h(ev)
- if ret is False:
- break
+ ret = self._dispatch(ev, self.inheritable_events.get(ev.__class__, []))
+ handled = handled or ret
+
+ ret = self._dispatch(ev, self.events.get(ev.__class__, []))
+ handled = handled or ret
+
+ if not handled:
+ LOG.info('unhandled event %s', ev)
class EventQueueBase(event.EventBase):