Skip to content

Commit 39b7d4b

Browse files
committed
Synchronize _collections.deque.
1 parent 71c240a commit 39b7d4b

File tree

1 file changed

+27
-0
lines changed

1 file changed

+27
-0
lines changed

graalpython/lib-graalpython/_collections.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2323
# DEALINGS IN THE SOFTWARE.
2424
import sys
25+
import _thread
2526

2627

2728
BLOCKLEN = 62
@@ -75,6 +76,7 @@ def __init__(self, iterable=None, maxlen=None):
7576
else:
7677
raise ValueError("maxlen must be non-negative")
7778

79+
self._mutex = _thread.RLock()
7880
self._maxlen = sys.maxsize if maxlen is None else maxlen
7981
self.leftblock = Block(None, None)
8082
self.rightblock = self.leftblock
@@ -87,6 +89,14 @@ def __init__(self, iterable=None, maxlen=None):
8789
if iterable is not None:
8890
self.extend(iterable)
8991

92+
def synchronized(fun):
93+
def fun_synchronized(self, *args):
94+
with self._mutex:
95+
return fun(self, *args)
96+
return fun_synchronized
97+
98+
99+
@synchronized
90100
def pop(self):
91101
"""Remove and return the rightmost element."""
92102
if self.len == 0:
@@ -123,16 +133,19 @@ def _checklock(self, lock):
123133
if lock is not self._lock:
124134
raise RuntimeError("deque mutated during iteration")
125135

136+
@synchronized
126137
def _trimleft(self):
127138
if self.len > self._maxlen:
128139
self.popleft()
129140
assert self.len == self._maxlen
130141

142+
@synchronized
131143
def _trimright(self):
132144
if self.len > self._maxlen:
133145
self.pop()
134146
assert self.len == self._maxlen
135147

148+
@synchronized
136149
def append(self, x):
137150
"""Add an element to the right side of the deque."""
138151
ri = self.rightindex + 1
@@ -147,6 +160,7 @@ def append(self, x):
147160
self._trimleft()
148161
self._modified()
149162

163+
@synchronized
150164
def appendleft(self, x):
151165
"""Add an element to the left side of the deque."""
152166
li = self.leftindex - 1
@@ -161,6 +175,7 @@ def appendleft(self, x):
161175
self._trimright()
162176
self._modified()
163177

178+
@synchronized
164179
def clear(self):
165180
"""Remove all elements from the deque."""
166181
self.leftblock = Block(None, None)
@@ -170,6 +185,7 @@ def clear(self):
170185
self.len = 0
171186
self._modified()
172187

188+
@synchronized
173189
def count(self, v):
174190
"""Return number of occurrences of value."""
175191
b = self.leftblock
@@ -194,6 +210,7 @@ def count(self, v):
194210

195211
return count
196212

213+
@synchronized
197214
def extend(self, iterable):
198215
"""Extend the right side of the deque with elements from the iterable"""
199216
# Handle case where id(deque) == id(iterable)
@@ -228,6 +245,7 @@ def __rmul__(self, times):
228245
def __hash__(self):
229246
raise TypeError("unhashable type: '%s'" % self.__name__)
230247

248+
@synchronized
231249
def extendleft(self, iterable):
232250
"""Extend the left side of the deque with elements from the iterable"""
233251
# Handle case where id(deque) == id(iterable)
@@ -242,6 +260,7 @@ def extendleft(self, iterable):
242260
break
243261
self.appendleft(obj)
244262

263+
@synchronized
245264
def popleft(self):
246265
"""Remove and return the leftmost element."""
247266
if self.len == 0:
@@ -266,6 +285,7 @@ def popleft(self):
266285
self._modified()
267286
return obj
268287

288+
@synchronized
269289
def remove(self, x):
270290
"""Remove first occurrence of value."""
271291
block = self.leftblock
@@ -286,6 +306,7 @@ def remove(self, x):
286306
index = 0
287307
raise ValueError("deque.remove(x): x not in deque")
288308

309+
@synchronized
289310
def reverse(self):
290311
"""Reverse *IN PLACE*."""
291312
li = self.leftindex
@@ -303,6 +324,7 @@ def reverse(self):
303324
rb = rb.leftlink
304325
ri = BLOCKLEN - 1
305326

327+
@synchronized
306328
def rotate(self, n=1):
307329
"""Rotate the deque n steps to the right (default n=1). If n is negative, rotates left."""
308330
len = self.len
@@ -343,6 +365,7 @@ def __repr__(self):
343365
maxlen_repr = ', maxlen=%d' % (self.maxlen,)
344366
return '%s(%s%s)' % (type(self).__name__, list_repr, maxlen_repr)
345367

368+
@synchronized
346369
def __compare__(self, other, op):
347370
if not isinstance(other, deque):
348371
return NotImplemented
@@ -415,6 +438,7 @@ def _check_index(self, idx):
415438
if idx < 0 or idx >= self.len:
416439
raise IndexError("deque index out of range")
417440

441+
@synchronized
418442
def index(self, v, start=0, stop=None):
419443
if stop is None:
420444
stop = self.len
@@ -517,6 +541,7 @@ def __delitem__(self, idx):
517541
self._check_index(idx)
518542
self.delitem(idx)
519543

544+
@synchronized
520545
def copy(self):
521546
"""Return a shallow copy of a deque."""
522547
if self._maxlen == sys.maxsize:
@@ -552,6 +577,8 @@ def maxlen(self):
552577
else:
553578
return self._maxlen
554579

580+
del synchronized
581+
555582

556583
class _DequeIter(object):
557584
def __init__(self, dq):

0 commit comments

Comments
 (0)