asyncio (Tulip issue 110): StreamReader.read() and StreamReader.readline() now

raise a RuntimeError, instead of using an assertion, if another coroutine is
already waiting for incoming data
This commit is contained in:
Victor Stinner 2014-01-23 17:40:03 +01:00
parent 8ce6e1100e
commit 183e347796

View file

@ -21,7 +21,7 @@ def open_connection(host=None, port=None, *,
"""A wrapper for create_connection() returning a (reader, writer) pair. """A wrapper for create_connection() returning a (reader, writer) pair.
The reader returned is a StreamReader instance; the writer is a The reader returned is a StreamReader instance; the writer is a
StreamWriter. StreamWriter instance.
The arguments are all the usual arguments to create_connection() The arguments are all the usual arguments to create_connection()
except protocol_factory; most common are positional host and port, except protocol_factory; most common are positional host and port,
@ -284,6 +284,16 @@ class StreamReader:
else: else:
self._paused = True self._paused = True
def _create_waiter(self, func_name):
# StreamReader uses a future to link the protocol feed_data() method
# to a read coroutine. Running two read coroutines at the same time
# would have an unexpected behaviour. It would not possible to know
# which coroutine would get the next data.
if self._waiter is not None:
raise RuntimeError('%s() called while another coroutine is '
'already waiting for incoming data' % func_name)
return futures.Future(loop=self._loop)
@tasks.coroutine @tasks.coroutine
def readline(self): def readline(self):
if self._exception is not None: if self._exception is not None:
@ -318,8 +328,7 @@ class StreamReader:
break break
if not_enough: if not_enough:
assert self._waiter is None self._waiter = self._create_waiter('readline')
self._waiter = futures.Future(loop=self._loop)
try: try:
yield from self._waiter yield from self._waiter
finally: finally:
@ -341,16 +350,14 @@ class StreamReader:
if n < 0: if n < 0:
while not self._eof: while not self._eof:
assert not self._waiter self._waiter = self._create_waiter('read')
self._waiter = futures.Future(loop=self._loop)
try: try:
yield from self._waiter yield from self._waiter
finally: finally:
self._waiter = None self._waiter = None
else: else:
if not self._byte_count and not self._eof: if not self._byte_count and not self._eof:
assert not self._waiter self._waiter = self._create_waiter('read')
self._waiter = futures.Future(loop=self._loop)
try: try:
yield from self._waiter yield from self._waiter
finally: finally: