class AsyncResult(object): """ Essentially a wrapper for a Tornado TracebackFuture """ def __init__(self, future=None): if future is not None: self._future = future else: self._future = TracebackFuture() self._future.add_done_callback(functools.partial(async_result_complete, self)) self._condition = threading.Condition() def ready(self): """Return `True` if and only if it holds a value or an exception""" return self._future.done() def successful(self): """Return `True` if and only if it is ready and holds a value""" return self._future.exception() is None @property def exception(self): return self._future.exception() def set(self, value=None): """Store the value. Wake up the waiters. :param value: Value to store as the result. Any waiters blocking on :meth:`get` or :meth:`wait` are woken up. Sequential calls to :meth:`wait` and :meth:`get` will not block at all.""" with self._condition: self._future.set_result(value) def set_exception(self, exception): """Store the exception. Wake up the waiters. :param exception: Exception to raise when fetching the value. Any waiters blocking on :meth:`get` or :meth:`wait` are woken up. Sequential calls to :meth:`wait` and :meth:`get` will not block at all.""" with self._condition: self._future.set_exception(exception) def get(self, block=True, timeout=None): """Return the stored value or raise the exception :param block: Whether this method should block or return immediately. :type block: bool :param timeout: How long to wait for a value when `block` is `True`. :type timeout: float If this instance already holds a value / an exception, return / raise it immediately. Otherwise, block until :meth:`set` or :meth:`set_exception` has been called or until the optional timeout occurs.""" with self._condition: if self.ready(): return self._future.result() elif block: self._condition.wait(timeout) return self._future.result() # if we get to this point we timeout raise KazooTimeoutError() def get_nowait(self): """Return the value or raise the exception without blocking. If nothing is available, raise the Timeout exception class on the associated :class:`IHandler` interface.""" return self._future.result() def wait(self, timeout=None): """Block until the instance is ready. :param timeout: How long to wait for a value :type timeout: float If this instance already holds a value / an exception, return / raise it immediately. Otherwise, block until :meth:`set` or :meth:`set_exception` has been called or until the optional timeout occurs.""" with self._condition: self._condition.wait(timeout) return self.ready() def rawlink(self, callback): """Register a callback to call when a value or an exception is set :param callback: A callback function to call after :meth:`set` or :meth:`set_exception` has been called. This function will be passed a single argument, this instance. :type callback: func """ def on_callback(future): callback(AsyncResult(future)) IOLoop.current().add_future(self._future, on_callback) def unlink(self, callback): """Remove the callback set by :meth:`rawlink` :param callback: A callback function to remove. :type callback: func """ def notify(self): self._condition.notify_all()