@@ -6,23 +6,27 @@ mod _collections {
6
6
use crate :: obj:: { objiter, objtype:: PyClassRef } ;
7
7
use crate :: pyobject:: {
8
8
IdProtocol , PyArithmaticValue :: * , PyClassImpl , PyComparisonValue , PyIterable , PyObjectRef ,
9
- PyRef , PyResult , PyValue ,
9
+ PyRef , PyResult , PyValue , ThreadSafe ,
10
10
} ;
11
11
use crate :: sequence;
12
12
use crate :: vm:: ReprGuard ;
13
13
use crate :: VirtualMachine ;
14
14
use itertools:: Itertools ;
15
- use std:: cell:: { Cell , RefCell } ;
16
15
use std:: collections:: VecDeque ;
16
+ use std:: sync:: { RwLock , RwLockReadGuard , RwLockWriteGuard } ;
17
+
18
+ use crossbeam_utils:: atomic:: AtomicCell ;
17
19
18
20
#[ pyclass( name = "deque" ) ]
19
- #[ derive( Debug , Clone ) ]
21
+ #[ derive( Debug ) ]
20
22
struct PyDeque {
21
- deque : RefCell < VecDeque < PyObjectRef > > ,
22
- maxlen : Cell < Option < usize > > ,
23
+ deque : RwLock < VecDeque < PyObjectRef > > ,
24
+ maxlen : AtomicCell < Option < usize > > ,
23
25
}
24
26
type PyDequeRef = PyRef < PyDeque > ;
25
27
28
+ impl ThreadSafe for PyDeque { }
29
+
26
30
impl PyValue for PyDeque {
27
31
fn class ( vm : & VirtualMachine ) -> PyClassRef {
28
32
vm. class ( "_collections" , "deque" )
@@ -36,8 +40,12 @@ mod _collections {
36
40
}
37
41
38
42
impl PyDeque {
39
- fn borrow_deque < ' a > ( & ' a self ) -> impl std:: ops:: Deref < Target = VecDeque < PyObjectRef > > + ' a {
40
- self . deque . borrow ( )
43
+ fn borrow_deque ( & self ) -> RwLockReadGuard < ' _ , VecDeque < PyObjectRef > > {
44
+ self . deque . read ( ) . unwrap ( )
45
+ }
46
+
47
+ fn borrow_deque_mut ( & self ) -> RwLockWriteGuard < ' _ , VecDeque < PyObjectRef > > {
48
+ self . deque . write ( ) . unwrap ( )
41
49
}
42
50
}
43
51
@@ -51,8 +59,8 @@ mod _collections {
51
59
vm : & VirtualMachine ,
52
60
) -> PyResult < PyRef < Self > > {
53
61
let py_deque = PyDeque {
54
- deque : RefCell :: default ( ) ,
55
- maxlen : maxlen . into ( ) ,
62
+ deque : RwLock :: default ( ) ,
63
+ maxlen : AtomicCell :: new ( maxlen ) ,
56
64
} ;
57
65
if let OptionalArg :: Present ( iter) = iter {
58
66
py_deque. extend ( iter, vm) ?;
@@ -62,36 +70,39 @@ mod _collections {
62
70
63
71
#[ pymethod]
64
72
fn append ( & self , obj : PyObjectRef ) {
65
- let mut deque = self . deque . borrow_mut ( ) ;
66
- if self . maxlen . get ( ) == Some ( deque. len ( ) ) {
73
+ let mut deque = self . borrow_deque_mut ( ) ;
74
+ if self . maxlen . load ( ) == Some ( deque. len ( ) ) {
67
75
deque. pop_front ( ) ;
68
76
}
69
77
deque. push_back ( obj) ;
70
78
}
71
79
72
80
#[ pymethod]
73
81
fn appendleft ( & self , obj : PyObjectRef ) {
74
- let mut deque = self . deque . borrow_mut ( ) ;
75
- if self . maxlen . get ( ) == Some ( deque. len ( ) ) {
82
+ let mut deque = self . borrow_deque_mut ( ) ;
83
+ if self . maxlen . load ( ) == Some ( deque. len ( ) ) {
76
84
deque. pop_back ( ) ;
77
85
}
78
86
deque. push_front ( obj) ;
79
87
}
80
88
81
89
#[ pymethod]
82
90
fn clear ( & self ) {
83
- self . deque . borrow_mut ( ) . clear ( )
91
+ self . borrow_deque_mut ( ) . clear ( )
84
92
}
85
93
86
94
#[ pymethod]
87
95
fn copy ( & self ) -> Self {
88
- self . clone ( )
96
+ PyDeque {
97
+ deque : RwLock :: new ( self . borrow_deque ( ) . clone ( ) ) ,
98
+ maxlen : AtomicCell :: new ( self . maxlen . load ( ) ) ,
99
+ }
89
100
}
90
101
91
102
#[ pymethod]
92
103
fn count ( & self , obj : PyObjectRef , vm : & VirtualMachine ) -> PyResult < usize > {
93
104
let mut count = 0 ;
94
- for elem in self . deque . borrow ( ) . iter ( ) {
105
+ for elem in self . borrow_deque ( ) . iter ( ) {
95
106
if vm. identical_or_equal ( elem, & obj) ? {
96
107
count += 1 ;
97
108
}
@@ -124,7 +135,7 @@ mod _collections {
124
135
stop : OptionalArg < usize > ,
125
136
vm : & VirtualMachine ,
126
137
) -> PyResult < usize > {
127
- let deque = self . deque . borrow ( ) ;
138
+ let deque = self . borrow_deque ( ) ;
128
139
let start = start. unwrap_or ( 0 ) ;
129
140
let stop = stop. unwrap_or_else ( || deque. len ( ) ) ;
130
141
for ( i, elem) in deque. iter ( ) . skip ( start) . take ( stop - start) . enumerate ( ) {
@@ -141,9 +152,9 @@ mod _collections {
141
152
142
153
#[ pymethod]
143
154
fn insert ( & self , idx : i32 , obj : PyObjectRef , vm : & VirtualMachine ) -> PyResult < ( ) > {
144
- let mut deque = self . deque . borrow_mut ( ) ;
155
+ let mut deque = self . borrow_deque_mut ( ) ;
145
156
146
- if self . maxlen . get ( ) == Some ( deque. len ( ) ) {
157
+ if self . maxlen . load ( ) == Some ( deque. len ( ) ) {
147
158
return Err ( vm. new_index_error ( "deque already at its maximum size" . to_owned ( ) ) ) ;
148
159
}
149
160
@@ -166,23 +177,21 @@ mod _collections {
166
177
167
178
#[ pymethod]
168
179
fn pop ( & self , vm : & VirtualMachine ) -> PyResult {
169
- self . deque
170
- . borrow_mut ( )
180
+ self . borrow_deque_mut ( )
171
181
. pop_back ( )
172
182
. ok_or_else ( || vm. new_index_error ( "pop from an empty deque" . to_owned ( ) ) )
173
183
}
174
184
175
185
#[ pymethod]
176
186
fn popleft ( & self , vm : & VirtualMachine ) -> PyResult {
177
- self . deque
178
- . borrow_mut ( )
187
+ self . borrow_deque_mut ( )
179
188
. pop_front ( )
180
189
. ok_or_else ( || vm. new_index_error ( "pop from an empty deque" . to_owned ( ) ) )
181
190
}
182
191
183
192
#[ pymethod]
184
193
fn remove ( & self , obj : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
185
- let mut deque = self . deque . borrow_mut ( ) ;
194
+ let mut deque = self . borrow_deque_mut ( ) ;
186
195
let mut idx = None ;
187
196
for ( i, elem) in deque. iter ( ) . enumerate ( ) {
188
197
if vm. identical_or_equal ( elem, & obj) ? {
@@ -196,13 +205,13 @@ mod _collections {
196
205
197
206
#[ pymethod]
198
207
fn reverse ( & self ) {
199
- self . deque
200
- . replace_with ( |deque| deque . iter ( ) . cloned ( ) . rev ( ) . collect ( ) ) ;
208
+ let rev : VecDeque < _ > = self . borrow_deque ( ) . iter ( ) . cloned ( ) . rev ( ) . collect ( ) ;
209
+ * self . borrow_deque_mut ( ) = rev;
201
210
}
202
211
203
212
#[ pymethod]
204
213
fn rotate ( & self , mid : OptionalArg < isize > ) {
205
- let mut deque = self . deque . borrow_mut ( ) ;
214
+ let mut deque = self . borrow_deque_mut ( ) ;
206
215
let mid = mid. unwrap_or ( 1 ) ;
207
216
if mid < 0 {
208
217
deque. rotate_left ( -mid as usize ) ;
@@ -213,26 +222,25 @@ mod _collections {
213
222
214
223
#[ pyproperty]
215
224
fn maxlen ( & self ) -> Option < usize > {
216
- self . maxlen . get ( )
225
+ self . maxlen . load ( )
217
226
}
218
227
219
228
#[ pyproperty( setter) ]
220
229
fn set_maxlen ( & self , maxlen : Option < usize > ) {
221
- self . maxlen . set ( maxlen) ;
230
+ self . maxlen . store ( maxlen) ;
222
231
}
223
232
224
233
#[ pymethod( name = "__repr__" ) ]
225
234
fn repr ( zelf : PyRef < Self > , vm : & VirtualMachine ) -> PyResult < String > {
226
235
let repr = if let Some ( _guard) = ReprGuard :: enter ( zelf. as_object ( ) ) {
227
236
let elements = zelf
228
- . deque
229
- . borrow ( )
237
+ . borrow_deque ( )
230
238
. iter ( )
231
239
. map ( |obj| vm. to_repr ( obj) )
232
240
. collect :: < Result < Vec < _ > , _ > > ( ) ?;
233
241
let maxlen = zelf
234
242
. maxlen
235
- . get ( )
243
+ . load ( )
236
244
. map ( |maxlen| format ! ( ", maxlen={}" , maxlen) )
237
245
. unwrap_or_default ( ) ;
238
246
format ! ( "deque([{}]{})" , elements. into_iter( ) . format( ", " ) , maxlen)
@@ -336,29 +344,29 @@ mod _collections {
336
344
337
345
#[ pymethod( name = "__mul__" ) ]
338
346
fn mul ( & self , n : isize ) -> Self {
339
- let deque: & VecDeque < _ > = & self . deque . borrow ( ) ;
347
+ let deque: & VecDeque < _ > = & self . borrow_deque ( ) ;
340
348
let mul = sequence:: seq_mul ( deque, n) ;
341
- let skipped = if let Some ( maxlen) = self . maxlen . get ( ) {
349
+ let skipped = if let Some ( maxlen) = self . maxlen . load ( ) {
342
350
mul. len ( ) - maxlen
343
351
} else {
344
352
0
345
353
} ;
346
354
let deque = mul. skip ( skipped) . cloned ( ) . collect ( ) ;
347
355
PyDeque {
348
- deque : RefCell :: new ( deque) ,
349
- maxlen : self . maxlen . clone ( ) ,
356
+ deque : RwLock :: new ( deque) ,
357
+ maxlen : AtomicCell :: new ( self . maxlen . load ( ) ) ,
350
358
}
351
359
}
352
360
353
361
#[ pymethod( name = "__len__" ) ]
354
362
fn len ( & self ) -> usize {
355
- self . deque . borrow ( ) . len ( )
363
+ self . borrow_deque ( ) . len ( )
356
364
}
357
365
358
366
#[ pymethod( name = "__iter__" ) ]
359
367
fn iter ( zelf : PyRef < Self > ) -> PyDequeIterator {
360
368
PyDequeIterator {
361
- position : Cell :: new ( 0 ) ,
369
+ position : AtomicCell :: new ( 0 ) ,
362
370
deque : zelf,
363
371
}
364
372
}
@@ -367,10 +375,12 @@ mod _collections {
367
375
#[ pyclass( name = "_deque_iterator" ) ]
368
376
#[ derive( Debug ) ]
369
377
struct PyDequeIterator {
370
- position : Cell < usize > ,
378
+ position : AtomicCell < usize > ,
371
379
deque : PyDequeRef ,
372
380
}
373
381
382
+ impl ThreadSafe for PyDequeIterator { }
383
+
374
384
impl PyValue for PyDequeIterator {
375
385
fn class ( vm : & VirtualMachine ) -> PyClassRef {
376
386
vm. class ( "_collections" , "_deque_iterator" )
@@ -381,9 +391,10 @@ mod _collections {
381
391
impl PyDequeIterator {
382
392
#[ pymethod( name = "__next__" ) ]
383
393
fn next ( & self , vm : & VirtualMachine ) -> PyResult {
384
- if self . position . get ( ) < self . deque . deque . borrow ( ) . len ( ) {
385
- let ret = self . deque . deque . borrow ( ) [ self . position . get ( ) ] . clone ( ) ;
386
- self . position . set ( self . position . get ( ) + 1 ) ;
394
+ let pos = self . position . fetch_add ( 1 ) ;
395
+ let deque = self . deque . borrow_deque ( ) ;
396
+ if pos < deque. len ( ) {
397
+ let ret = deque[ pos] . clone ( ) ;
387
398
Ok ( ret)
388
399
} else {
389
400
Err ( objiter:: new_stop_iteration ( vm) )
0 commit comments