Mercurial > hg
comparison mercurial/worker.py @ 49233:520722523955
worker: implement _blockingreader.readinto() (issue6444)
The core logic for readinto() was already implemented in read(), so this is
mostly extracting that code into its own method.
Another fix for issue6444 was committed to the stable branch: 2fe4efaa59af.
That is a minimal fix that implements readinto() only on Python versions that
require readinto() (3.8.0 and 3.8.1), which is the right approach for the
stable branch. However, I think that this changeset has its value. It improves
performance in cases when pickle can use readinto(), it reduces code
duplication compared to the other patch, and by defining readinto() on all
Python versions, it makes behavior more consistent across all Python versions.
This changesets reverts the other change.
author | Manuel Jacob <me@manueljacob.de> |
---|---|
date | Sun, 22 May 2022 00:10:58 +0200 |
parents | 4c57ce494a4e |
children | 395f28064826 |
comparison
equal
deleted
inserted
replaced
49232:4c57ce494a4e | 49233:520722523955 |
---|---|
77 """ | 77 """ |
78 | 78 |
79 def __init__(self, wrapped): | 79 def __init__(self, wrapped): |
80 self._wrapped = wrapped | 80 self._wrapped = wrapped |
81 | 81 |
82 # Do NOT implement readinto() by making it delegate to | |
83 # _wrapped.readinto(), since that is unbuffered. The unpickler is fine | |
84 # with just read() and readline(), so we don't need to implement it. | |
85 | |
86 if (3, 8, 0) <= sys.version_info[:3] < (3, 8, 2): | |
87 | |
88 # This is required for python 3.8, prior to 3.8.2. See issue6444. | |
89 def readinto(self, b): | |
90 pos = 0 | |
91 size = len(b) | |
92 | |
93 while pos < size: | |
94 ret = self._wrapped.readinto(b[pos:]) | |
95 if not ret: | |
96 break | |
97 pos += ret | |
98 | |
99 return pos | |
100 | |
101 def readline(self): | 82 def readline(self): |
102 return self._wrapped.readline() | 83 return self._wrapped.readline() |
103 | 84 |
104 # issue multiple reads until size is fulfilled (or EOF is encountered) | 85 def readinto(self, buf): |
105 def read(self, size=-1): | |
106 if size < 0: | |
107 return self._wrapped.readall() | |
108 | |
109 buf = bytearray(size) | |
110 pos = 0 | 86 pos = 0 |
87 size = len(buf) | |
111 | 88 |
112 with memoryview(buf) as view: | 89 with memoryview(buf) as view: |
113 while pos < size: | 90 while pos < size: |
114 with view[pos:] as subview: | 91 with view[pos:] as subview: |
115 ret = self._wrapped.readinto(subview) | 92 ret = self._wrapped.readinto(subview) |
116 if not ret: | 93 if not ret: |
117 break | 94 break |
118 pos += ret | 95 pos += ret |
119 | 96 |
120 del buf[pos:] | 97 return pos |
98 | |
99 # issue multiple reads until size is fulfilled (or EOF is encountered) | |
100 def read(self, size=-1): | |
101 if size < 0: | |
102 return self._wrapped.readall() | |
103 | |
104 buf = bytearray(size) | |
105 n_read = self.readinto(buf) | |
106 del buf[n_read:] | |
121 return bytes(buf) | 107 return bytes(buf) |
122 | 108 |
123 | 109 |
124 if pycompat.isposix or pycompat.iswindows: | 110 if pycompat.isposix or pycompat.iswindows: |
125 _STARTUP_COST = 0.01 | 111 _STARTUP_COST = 0.01 |