@@ -220,6 +220,7 @@ def __init__(self, limit=_DEFAULT_LIMIT, loop=None):
220220 if loop is None :
221221 loop = events .get_event_loop ()
222222 self ._loop = loop
223+ # TODO: Use a bytearray for a buffer, like the transport.
223224 self ._buffer = collections .deque () # Deque of bytes objects.
224225 self ._byte_count = 0 # Bytes in buffer.
225226 self ._eof = False # Whether we're done.
@@ -384,15 +385,23 @@ def readexactly(self, n):
384385 if self ._exception is not None :
385386 raise self ._exception
386387
387- if n <= 0 :
388- return b''
388+ # There used to be "optimized" code here. It created its own
389+ # Future and waited until self._buffer had at least the n
390+ # bytes, then called read(n). Unfortunately, this could pause
391+ # the transport if the argument was larger than the pause
392+ # limit (which is twice self._limit). So now we just read()
393+ # into a local buffer.
394+
395+ blocks = []
396+ while n > 0 :
397+ block = yield from self .read (n )
398+ if not block :
399+ break
400+ blocks .append (block )
401+ n -= len (block )
389402
390- while self ._byte_count < n and not self ._eof :
391- assert not self ._waiter
392- self ._waiter = futures .Future (loop = self ._loop )
393- try :
394- yield from self ._waiter
395- finally :
396- self ._waiter = None
403+ # TODO: Raise EOFError if we break before n == 0? (That would
404+ # be a change in specification, but I've always had to add an
405+ # explicit size check to the caller.)
397406
398- return ( yield from self . read ( n ) )
407+ return b'' . join ( blocks )
0 commit comments