From: Ben Darnell Date: Sun, 26 Jan 2014 03:18:08 +0000 (-0500) Subject: tornado.concurrent.Future is now always thread-unsafe. X-Git-Tag: v4.0.0b1~131 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dce2ffe1b3e20e0592720e5d80709130a11d315e;p=thirdparty%2Ftornado.git tornado.concurrent.Future is now always thread-unsafe. This improves performance and provides more consistent semantics (independent of the presence or absence of the concurrent.futures package). The parts of Tornado that accept Futures will accept both Tornado's thread-unsafe Futures and the thread-safe concurrent.futures.Future. --- diff --git a/tornado/concurrent.py b/tornado/concurrent.py index a9002b16a..a1b2d57c8 100644 --- a/tornado/concurrent.py +++ b/tornado/concurrent.py @@ -40,7 +40,7 @@ class ReturnValueIgnoredError(Exception): pass -class _DummyFuture(object): +class Future(object): def __init__(self): self._done = False self._result = None @@ -97,11 +97,14 @@ class _DummyFuture(object): cb(self) self._callbacks = None + if futures is None: - Future = _DummyFuture + FUTURES = Future else: - Future = futures.Future + FUTURES = (futures.Future, Future) +def is_future(x): + return isinstance(x, FUTURES) class TracebackFuture(Future): """Subclass of `Future` which can store a traceback with diff --git a/tornado/gen.py b/tornado/gen.py index aa931b457..eacff4b83 100644 --- a/tornado/gen.py +++ b/tornado/gen.py @@ -87,7 +87,7 @@ import itertools import sys import types -from tornado.concurrent import Future, TracebackFuture +from tornado.concurrent import TracebackFuture, is_future from tornado.ioloop import IOLoop from tornado.stack_context import ExceptionStackContext, wrap @@ -426,7 +426,7 @@ class Multi(YieldPoint): children = children.values() self.children = [] for i in children: - if isinstance(i, Future): + if is_future(i): i = YieldFuture(i) self.children.append(i) assert all(isinstance(i, YieldPoint) for i in self.children) @@ -549,7 +549,7 @@ class Runner(object): raise if isinstance(yielded, (list, dict)): yielded = Multi(yielded) - elif isinstance(yielded, Future): + elif is_future(yielded): yielded = YieldFuture(yielded) if isinstance(yielded, YieldPoint): self.yield_point = yielded diff --git a/tornado/ioloop.py b/tornado/ioloop.py index d69f25cc9..77fb46591 100644 --- a/tornado/ioloop.py +++ b/tornado/ioloop.py @@ -41,7 +41,7 @@ import threading import time import traceback -from tornado.concurrent import Future, TracebackFuture +from tornado.concurrent import TracebackFuture, is_future from tornado.log import app_log, gen_log from tornado import stack_context from tornado.util import Configurable @@ -391,7 +391,7 @@ class IOLoop(Configurable): future_cell[0] = TracebackFuture() future_cell[0].set_exc_info(sys.exc_info()) else: - if isinstance(result, Future): + if is_future(result): future_cell[0] = result else: future_cell[0] = TracebackFuture() @@ -482,7 +482,7 @@ class IOLoop(Configurable): The callback is invoked with one argument, the `.Future`. """ - assert isinstance(future, Future) + assert is_future(future) callback = stack_context.wrap(callback) future.add_done_callback( lambda future: self.add_callback(callback, future)) diff --git a/tornado/test/concurrent_test.py b/tornado/test/concurrent_test.py index 849337ed6..5e93ad6a4 100644 --- a/tornado/test/concurrent_test.py +++ b/tornado/test/concurrent_test.py @@ -28,7 +28,6 @@ from tornado.iostream import IOStream from tornado import stack_context from tornado.tcpserver import TCPServer from tornado.testing import AsyncTestCase, LogTrapTestCase, bind_unused_port, gen_test -from tornado.test.util import unittest try: @@ -113,13 +112,6 @@ class ReturnFutureTest(AsyncTestCase): self.assertIs(future, future2) self.assertEqual(future.result(), 42) - @unittest.skipIf(futures is None, "futures module not present") - def test_timeout_future(self): - with self.assertRaises(futures.TimeoutError): - future = self.async_future() - # Do not call self.wait() - future.result(timeout=.1) - @gen_test def test_async_future_gen(self): result = yield self.async_future()