]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Fold TracebackFuture into Future.
authorBen Darnell <ben@bendarnell.com>
Mon, 17 Feb 2014 01:29:37 +0000 (20:29 -0500)
committerBen Darnell <ben@bendarnell.com>
Mon, 17 Feb 2014 01:29:37 +0000 (20:29 -0500)
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.

tornado/concurrent.py

index a1b2d57c87470dfac03a25f6a5a6b7d2be5ef5a7..ab7b65c3ad4817b8e42ba073621f3c2a8bf3468a 100644 (file)
@@ -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 @@ class Future(object):
         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 @@ class Future(object):
         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 @@ class Future(object):
             cb(self)
         self._callbacks = None
 
+TracebackFuture = Future
 
 if futures is None:
     FUTURES = Future
@@ -106,33 +134,6 @@ else:
 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):