Commit 20f0c8be authored by Denis Bilenko's avatar Denis Bilenko

event: make sure callback passed to rawlink() is always called in hub's greenlet

parent c5057e28
...@@ -10,6 +10,7 @@ class Event(object): ...@@ -10,6 +10,7 @@ class Event(object):
def __init__(self): def __init__(self):
self._links = set() self._links = set()
self._value = _NONE self._value = _NONE
self._notifier = None
def ready(self): def ready(self):
return self._value is not _NONE return self._value is not _NONE
...@@ -20,12 +21,11 @@ class Event(object): ...@@ -20,12 +21,11 @@ class Event(object):
return self._value return self._value
def rawlink(self, callback): def rawlink(self, callback):
if self._value is _NONE: if not callable(callback):
self._links.add(callback) raise TypeError('Expected callable: %r' % (callback, ))
else: self._links.add(callback)
# QQQ switch won't work as a callback! if self.ready() and self._notifier is None:
# QQQ should I schedule the callback here too, like Greenlet.rawlink does? self._notifier = core.active_event(self._notify_links)
callback(self)
def unlink(self, callback): def unlink(self, callback):
self._links.discard(callback) self._links.discard(callback)
...@@ -38,22 +38,25 @@ class Event(object): ...@@ -38,22 +38,25 @@ class Event(object):
oldvalue = self._value oldvalue = self._value
self._value = value self._value = value
if oldvalue is _NONE: if oldvalue is _NONE:
if self._links: if self._links and self._notifier is None:
core.active_event(self._notify_links) self._notifier = core.active_event(self._notify_links)
def _notify_links(self): def _notify_links(self):
assert getcurrent() is get_hub() try:
while self._links: assert getcurrent() is get_hub()
link = self._links.pop() while self._links:
try: link = self._links.pop()
link(self)
except:
traceback.print_exc()
try: try:
sys.stderr.write('Failed to notify link %r of %r\n\n' % (link, self)) link(self)
except: except:
pass traceback.print_exc()
# even if g is left unscheduled, it will be deallocated because there are no more references to it try:
sys.stderr.write('Failed to notify link %r of %r\n\n' % (link, self))
except:
pass
# even if g is left unscheduled, it will be deallocated because there are no more references to it
finally:
self._notifier = None
def get(self, block=True, timeout=None): def get(self, block=True, timeout=None):
if self._value is not _NONE: if self._value is not _NONE:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment