@@ -6,12 +6,13 @@ use crate::obj::objtype::PyClassRef;
6
6
use crate :: obj:: { objbool, objiter} ;
7
7
use crate :: pyobject:: {
8
8
Either , IntoPyObject , PyClassImpl , PyIterable , PyObjectRef , PyRef , PyResult , PyValue ,
9
- TryFromObject ,
9
+ ThreadSafe , TryFromObject ,
10
10
} ;
11
11
use crate :: VirtualMachine ;
12
12
13
- use std:: cell:: { Cell , RefCell } ;
13
+ use std:: cell:: Cell ;
14
14
use std:: fmt;
15
+ use std:: sync:: { RwLock , RwLockReadGuard , RwLockWriteGuard } ;
15
16
16
17
struct ArrayTypeSpecifierError {
17
18
_priv : ( ) ,
@@ -223,8 +224,11 @@ def_array_enum!(
223
224
#[ pyclass( name = "array" ) ]
224
225
#[ derive( Debug ) ]
225
226
pub struct PyArray {
226
- array : RefCell < ArrayContentType > ,
227
+ array : RwLock < ArrayContentType > ,
227
228
}
229
+
230
+ impl ThreadSafe for PyArray { }
231
+
228
232
pub type PyArrayRef = PyRef < PyArray > ;
229
233
230
234
impl PyValue for PyArray {
@@ -235,6 +239,14 @@ impl PyValue for PyArray {
235
239
236
240
#[ pyimpl( flags( BASETYPE ) ) ]
237
241
impl PyArray {
242
+ fn borrow_value ( & self ) -> RwLockReadGuard < ' _ , ArrayContentType > {
243
+ self . array . read ( ) . unwrap ( )
244
+ }
245
+
246
+ fn borrow_value_mut ( & self ) -> RwLockWriteGuard < ' _ , ArrayContentType > {
247
+ self . array . write ( ) . unwrap ( )
248
+ }
249
+
238
250
#[ pyslot]
239
251
fn tp_new (
240
252
cls : PyClassRef ,
@@ -253,7 +265,7 @@ impl PyArray {
253
265
let array =
254
266
ArrayContentType :: from_char ( spec) . map_err ( |err| vm. new_value_error ( err. to_string ( ) ) ) ?;
255
267
let zelf = PyArray {
256
- array : RefCell :: new ( array) ,
268
+ array : RwLock :: new ( array) ,
257
269
} ;
258
270
if let OptionalArg :: Present ( init) = init {
259
271
zelf. extend ( init, vm) ?;
@@ -263,33 +275,33 @@ impl PyArray {
263
275
264
276
#[ pyproperty]
265
277
fn typecode ( & self ) -> String {
266
- self . array . borrow ( ) . typecode ( ) . to_string ( )
278
+ self . borrow_value ( ) . typecode ( ) . to_string ( )
267
279
}
268
280
269
281
#[ pyproperty]
270
282
fn itemsize ( & self ) -> usize {
271
- self . array . borrow ( ) . itemsize ( )
283
+ self . borrow_value ( ) . itemsize ( )
272
284
}
273
285
274
286
#[ pymethod]
275
287
fn append ( & self , x : PyObjectRef , vm : & VirtualMachine ) -> PyResult < ( ) > {
276
- self . array . borrow_mut ( ) . push ( x, vm)
288
+ self . borrow_value_mut ( ) . push ( x, vm)
277
289
}
278
290
279
291
#[ pymethod]
280
292
fn buffer_info ( & self ) -> ( usize , usize ) {
281
- let array = self . array . borrow ( ) ;
293
+ let array = self . borrow_value ( ) ;
282
294
( array. addr ( ) , array. len ( ) )
283
295
}
284
296
285
297
#[ pymethod]
286
298
fn count ( & self , x : PyObjectRef , vm : & VirtualMachine ) -> PyResult < usize > {
287
- self . array . borrow ( ) . count ( x, vm)
299
+ self . borrow_value ( ) . count ( x, vm)
288
300
}
289
301
290
302
#[ pymethod]
291
303
fn extend ( & self , iter : PyIterable , vm : & VirtualMachine ) -> PyResult < ( ) > {
292
- let mut array = self . array . borrow_mut ( ) ;
304
+ let mut array = self . borrow_value_mut ( ) ;
293
305
for elem in iter. iter ( vm) ? {
294
306
array. push ( elem?, vm) ?;
295
307
}
@@ -299,20 +311,19 @@ impl PyArray {
299
311
#[ pymethod]
300
312
fn frombytes ( & self , b : PyBytesRef , vm : & VirtualMachine ) -> PyResult < ( ) > {
301
313
let b = b. get_value ( ) ;
302
- let itemsize = self . array . borrow ( ) . itemsize ( ) ;
314
+ let itemsize = self . borrow_value ( ) . itemsize ( ) ;
303
315
if b. len ( ) % itemsize != 0 {
304
316
return Err ( vm. new_value_error ( "bytes length not a multiple of item size" . to_owned ( ) ) ) ;
305
317
}
306
318
if b. len ( ) / itemsize > 0 {
307
- self . array . borrow_mut ( ) . frombytes ( & b) ;
319
+ self . borrow_value_mut ( ) . frombytes ( & b) ;
308
320
}
309
321
Ok ( ( ) )
310
322
}
311
323
312
324
#[ pymethod]
313
325
fn index ( & self , x : PyObjectRef , vm : & VirtualMachine ) -> PyResult < usize > {
314
- self . array
315
- . borrow ( )
326
+ self . borrow_value ( )
316
327
. index ( x, vm) ?
317
328
. ok_or_else ( || vm. new_value_error ( "x not in array" . to_owned ( ) ) )
318
329
}
@@ -335,27 +346,27 @@ impl PyArray {
335
346
i
336
347
}
337
348
} ;
338
- self . array . borrow_mut ( ) . insert ( i, x, vm)
349
+ self . borrow_value_mut ( ) . insert ( i, x, vm)
339
350
}
340
351
341
352
#[ pymethod]
342
353
fn pop ( & self , i : OptionalArg < isize > , vm : & VirtualMachine ) -> PyResult {
343
354
if self . len ( ) == 0 {
344
355
Err ( vm. new_index_error ( "pop from empty array" . to_owned ( ) ) )
345
356
} else {
346
- let i = self . array . borrow ( ) . idx ( i. unwrap_or ( -1 ) , "pop" , vm) ?;
347
- self . array . borrow_mut ( ) . pop ( i, vm)
357
+ let i = self . borrow_value ( ) . idx ( i. unwrap_or ( -1 ) , "pop" , vm) ?;
358
+ self . borrow_value_mut ( ) . pop ( i, vm)
348
359
}
349
360
}
350
361
351
362
#[ pymethod]
352
363
pub ( crate ) fn tobytes ( & self ) -> Vec < u8 > {
353
- self . array . borrow ( ) . tobytes ( )
364
+ self . borrow_value ( ) . tobytes ( )
354
365
}
355
366
356
367
#[ pymethod]
357
368
fn tolist ( & self , vm : & VirtualMachine ) -> PyResult {
358
- let array = self . array . borrow ( ) ;
369
+ let array = self . borrow_value ( ) ;
359
370
let mut v = Vec :: with_capacity ( array. len ( ) ) ;
360
371
for obj in array. iter ( vm) {
361
372
v. push ( obj?) ;
@@ -365,12 +376,12 @@ impl PyArray {
365
376
366
377
#[ pymethod]
367
378
fn reverse ( & self ) {
368
- self . array . borrow_mut ( ) . reverse ( )
379
+ self . borrow_value_mut ( ) . reverse ( )
369
380
}
370
381
371
382
#[ pymethod( magic) ]
372
383
fn getitem ( & self , needle : Either < isize , PySliceRef > , vm : & VirtualMachine ) -> PyResult {
373
- self . array . borrow ( ) . getitem ( needle, vm)
384
+ self . borrow_value ( ) . getitem ( needle, vm)
374
385
}
375
386
376
387
#[ pymethod( magic) ]
@@ -380,15 +391,15 @@ impl PyArray {
380
391
obj : PyObjectRef ,
381
392
vm : & VirtualMachine ,
382
393
) -> PyResult < ( ) > {
383
- self . array . borrow_mut ( ) . setitem ( needle, obj, vm)
394
+ self . borrow_value_mut ( ) . setitem ( needle, obj, vm)
384
395
}
385
396
386
397
#[ pymethod( name = "__eq__" ) ]
387
398
fn eq ( lhs : PyObjectRef , rhs : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
388
399
let lhs = class_or_notimplemented ! ( vm, Self , lhs) ;
389
400
let rhs = class_or_notimplemented ! ( vm, Self , rhs) ;
390
- let lhs = lhs. array . borrow ( ) ;
391
- let rhs = rhs. array . borrow ( ) ;
401
+ let lhs = lhs. borrow_value ( ) ;
402
+ let rhs = rhs. borrow_value ( ) ;
392
403
if lhs. len ( ) != rhs. len ( ) {
393
404
Ok ( vm. new_bool ( false ) )
394
405
} else {
@@ -404,7 +415,7 @@ impl PyArray {
404
415
405
416
#[ pymethod( name = "__len__" ) ]
406
417
fn len ( & self ) -> usize {
407
- self . array . borrow ( ) . len ( )
418
+ self . borrow_value ( ) . len ( )
408
419
}
409
420
410
421
#[ pymethod( name = "__iter__" ) ]
@@ -433,11 +444,10 @@ impl PyValue for PyArrayIter {
433
444
impl PyArrayIter {
434
445
#[ pymethod( name = "__next__" ) ]
435
446
fn next ( & self , vm : & VirtualMachine ) -> PyResult {
436
- if self . position . get ( ) < self . array . array . borrow ( ) . len ( ) {
447
+ if self . position . get ( ) < self . array . borrow_value ( ) . len ( ) {
437
448
let ret = self
438
449
. array
439
- . array
440
- . borrow ( )
450
+ . borrow_value ( )
441
451
. getitem_by_idx ( self . position . get ( ) , vm)
442
452
. unwrap ( ) ?;
443
453
self . position . set ( self . position . get ( ) + 1 ) ;
0 commit comments