From: Ben Darnell Date: Fri, 31 Aug 2012 01:58:40 +0000 (-0400) Subject: Add IOLoop.add_future to return to the IOLoop after a future has completed. X-Git-Tag: v3.0.0~263^2~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cb2c088bdd449f5b346764c2e4486081418f732b;p=thirdparty%2Ftornado.git Add IOLoop.add_future to return to the IOLoop after a future has completed. --- diff --git a/tornado/ioloop.py b/tornado/ioloop.py index 70eb5564b..7525bb099 100644 --- a/tornado/ioloop.py +++ b/tornado/ioloop.py @@ -30,6 +30,7 @@ from __future__ import absolute_import, division, with_statement import datetime import errno +import functools import heapq import os import logging @@ -46,6 +47,11 @@ try: except ImportError: signal = None +try: + from concurrent import futures +except ImportError: + futures = None + from tornado.platform.auto import set_close_exec, Waker @@ -416,6 +422,17 @@ class IOLoop(object): # avoid it when we can. self._waker.wake() + def add_future(self, future, callback): + """Schedules a callback on the IOLoop when the given future is finished. + + Requires the concurrent.futures module (standard in python 3.2+, + available via "pip install futures" in older versions). + """ + assert isinstance(future, futures.Future) + future.add_done_callback( + lambda future: self.add_callback( + functools.partial(callback, future))) + def _run_callback(self, callback): try: callback() diff --git a/tornado/test/ioloop_test.py b/tornado/test/ioloop_test.py index 4e5e123c9..1413a1846 100644 --- a/tornado/test/ioloop_test.py +++ b/tornado/test/ioloop_test.py @@ -11,6 +11,11 @@ from tornado.netutil import bind_sockets from tornado.testing import AsyncTestCase, LogTrapTestCase, get_unused_port from tornado.test.util import unittest +try: + from concurrent import futures +except ImportError: + futures = None + class TestIOLoop(AsyncTestCase, LogTrapTestCase): def test_add_callback_wakeup(self): @@ -49,5 +54,17 @@ class TestIOLoop(AsyncTestCase, LogTrapTestCase): sock.close() +class TestIOLoopFutures(AsyncTestCase, LogTrapTestCase): + def test_add_future_threads(self): + with futures.ThreadPoolExecutor(1) as pool: + self.io_loop.add_future(pool.submit(lambda: None), + lambda future: self.stop(future)) + future = self.wait() + self.assertTrue(future.done()) + self.assertTrue(future.result() is None) +TestIOLoopFutures = unittest.skipIf( + futures is None, "futures module is not present")(TestIOLoopFutures) + + if __name__ == "__main__": unittest.main()