Permalink
Browse files

Fold TracebackFuture into Future.

Since it is no longer possible for TracebackFuture to modify
concurrent.futures.Future instead, there is no need for separate
classes.  Removing the subclass speeds things up a bit by removing
a level of indirection.

Also microoptimized a few methods of Future.
  • Loading branch information...
1 parent 184d796 commit 8e07f3d86524b5f0fb5c3f4057085f3dd9c83b95 @bdarnell bdarnell committed Feb 17, 2014
Showing with 32 additions and 31 deletions.
  1. +32 −31 tornado/concurrent.py
View
@@ -41,10 +41,23 @@ class ReturnValueIgnoredError(Exception):
class Future(object):
+ """Placeholder for an asynchronous result.
+
+ Similar to `concurrent.futures.Future`, but not thread-safe (and
+ therefore faster for use with single-threaded event loops.
+
+ In addition to ``exception`` and ``set_exception``, methods ``exc_info``
+ and ``set_exc_info`` are supported to capture tracebacks in Python 2.
+ The traceback is automatically available in Python 3, but in the
+ Python 2 futures backport this information is discarded.
+ This functionality was previously available in a separate class
+ ``TracebackFuture``, which is now a deprecated alias for this class.
+ """
def __init__(self):
self._done = False
self._result = None
self._exception = None
+ self._exc_info = None
self._callbacks = []
def cancel(self):
@@ -60,16 +73,20 @@ def done(self):
return self._done
def result(self, timeout=None):
- self._check_done()
- if self._exception:
+ if self._result is not None:
+ return self._result
+ if self._exc_info is not None:
+ raise_exc_info(self._exc_info)
+ elif self._exception is not None:
raise self._exception
+ self._check_done()
return self._result
def exception(self, timeout=None):
- self._check_done()
- if self._exception:
+ if self._exception is not None:
return self._exception
else:
+ self._check_done()
return None
def add_done_callback(self, fn):
@@ -86,6 +103,16 @@ def set_exception(self, exception):
self._exception = exception
self._set_done()
+ def exc_info(self):
+ return self._exc_info
+
+ def set_exc_info(self, exc_info):
+ """Traceback-aware replacement for
+ `~concurrent.futures.Future.set_exception`.
+ """
+ self._exc_info = exc_info
+ self.set_exception(exc_info[1])
+
def _check_done(self):
if not self._done:
raise Exception("DummyFuture does not support blocking for results")
@@ -97,6 +124,7 @@ def _set_done(self):
cb(self)
self._callbacks = None
+TracebackFuture = Future
if futures is None:
FUTURES = Future
@@ -106,33 +134,6 @@ def _set_done(self):
def is_future(x):
return isinstance(x, FUTURES)
-class TracebackFuture(Future):
- """Subclass of `Future` which can store a traceback with
- exceptions.
-
- The traceback is automatically available in Python 3, but in the
- Python 2 futures backport this information is discarded.
- """
- def __init__(self):
- super(TracebackFuture, self).__init__()
- self.__exc_info = None
-
- def exc_info(self):
- return self.__exc_info
-
- def set_exc_info(self, exc_info):
- """Traceback-aware replacement for
- `~concurrent.futures.Future.set_exception`.
- """
- self.__exc_info = exc_info
- self.set_exception(exc_info[1])
-
- def result(self, timeout=None):
- if self.__exc_info is not None:
- raise_exc_info(self.__exc_info)
- else:
- return super(TracebackFuture, self).result(timeout=timeout)
-
class DummyExecutor(object):
def submit(self, fn, *args, **kwargs):

0 comments on commit 8e07f3d

Please sign in to comment.