Skip to content

Commit 8bdf755

Browse files
authored
Merge pull request #2587 from bdarnell/opt
ioloop: Micro-optimize IOLoop.add_future
2 parents 89993db + 64de184 commit 8bdf755

File tree

2 files changed

+29
-13
lines changed

2 files changed

+29
-13
lines changed

tornado/ioloop.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import asyncio
3434
import concurrent.futures
3535
import datetime
36+
import functools
3637
import logging
3738
import numbers
3839
import os
@@ -676,10 +677,25 @@ def add_future(
676677
awaitables (unlike most of Tornado where the two are
677678
interchangeable).
678679
"""
679-
assert is_future(future)
680-
future_add_done_callback(
681-
future, lambda future: self.add_callback(callback, future)
682-
)
680+
if isinstance(future, Future):
681+
# Note that we specifically do not want the inline behavior of
682+
# tornado.concurrent.future_add_done_callback. We always want
683+
# this callback scheduled on the next IOLoop iteration (which
684+
# asyncio.Future always does).
685+
#
686+
# Wrap the callback in self._run_callback so we control
687+
# the error logging (i.e. it goes to tornado.log.app_log
688+
# instead of asyncio's log).
689+
future.add_done_callback(
690+
lambda f: self._run_callback(functools.partial(callback, future))
691+
)
692+
else:
693+
assert is_future(future)
694+
# For concurrent futures, we use self.add_callback, so
695+
# it's fine if future_add_done_callback inlines that call.
696+
future_add_done_callback(
697+
future, lambda f: self.add_callback(callback, future)
698+
)
683699

684700
def run_in_executor(
685701
self,

tornado/test/iostream_test.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -946,29 +946,29 @@ def test_start_tls_smtp(self):
946946
def test_handshake_fail(self):
947947
server_future = self.server_start_tls(_server_ssl_options())
948948
# Certificates are verified with the default configuration.
949-
client_future = self.client_start_tls(server_hostname="localhost")
950949
with ExpectLog(gen_log, "SSL Error"):
950+
client_future = self.client_start_tls(server_hostname="localhost")
951951
with self.assertRaises(ssl.SSLError):
952952
yield client_future
953-
with self.assertRaises((ssl.SSLError, socket.error)):
954-
yield server_future
953+
with self.assertRaises((ssl.SSLError, socket.error)):
954+
yield server_future
955955

956956
@gen_test
957957
def test_check_hostname(self):
958958
# Test that server_hostname parameter to start_tls is being used.
959959
# The check_hostname functionality is only available in python 2.7 and
960960
# up and in python 3.4 and up.
961961
server_future = self.server_start_tls(_server_ssl_options())
962-
client_future = self.client_start_tls(
963-
ssl.create_default_context(), server_hostname="127.0.0.1"
964-
)
965962
with ExpectLog(gen_log, "SSL Error"):
963+
client_future = self.client_start_tls(
964+
ssl.create_default_context(), server_hostname="127.0.0.1"
965+
)
966966
with self.assertRaises(ssl.SSLError):
967967
# The client fails to connect with an SSL error.
968968
yield client_future
969-
with self.assertRaises(Exception):
970-
# The server fails to connect, but the exact error is unspecified.
971-
yield server_future
969+
with self.assertRaises(Exception):
970+
# The server fails to connect, but the exact error is unspecified.
971+
yield server_future
972972

973973

974974
class WaitForHandshakeTest(AsyncTestCase):

0 commit comments

Comments
 (0)