1
- use std:: cell:: RefCell ;
2
1
use std:: collections:: { HashMap , HashSet } ;
3
2
use std:: fmt;
3
+ use std:: sync:: RwLock ;
4
4
5
5
use super :: objdict:: PyDictRef ;
6
6
use super :: objlist:: PyList ;
@@ -12,7 +12,7 @@ use super::objweakref::PyWeak;
12
12
use crate :: function:: { OptionalArg , PyFuncArgs } ;
13
13
use crate :: pyobject:: {
14
14
IdProtocol , PyAttributes , PyClassImpl , PyContext , PyIterable , PyObject , PyObjectRef , PyRef ,
15
- PyResult , PyValue , TypeProtocol ,
15
+ PyResult , PyValue , ThreadSafe , TypeProtocol ,
16
16
} ;
17
17
use crate :: slots:: { PyClassSlots , PyTpFlags } ;
18
18
use crate :: vm:: VirtualMachine ;
@@ -27,11 +27,13 @@ pub struct PyClass {
27
27
pub name : String ,
28
28
pub bases : Vec < PyClassRef > ,
29
29
pub mro : Vec < PyClassRef > ,
30
- pub subclasses : RefCell < Vec < PyWeak > > ,
31
- pub attributes : RefCell < PyAttributes > ,
32
- pub slots : RefCell < PyClassSlots > ,
30
+ pub subclasses : RwLock < Vec < PyWeak > > ,
31
+ pub attributes : RwLock < PyAttributes > ,
32
+ pub slots : RwLock < PyClassSlots > ,
33
33
}
34
34
35
+ impl ThreadSafe for PyClass { }
36
+
35
37
impl fmt:: Display for PyClass {
36
38
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
37
39
fmt:: Display :: fmt ( & self . name , f)
@@ -97,7 +99,8 @@ impl PyClassRef {
97
99
#[ pyproperty( magic) ]
98
100
fn qualname ( self , vm : & VirtualMachine ) -> PyObjectRef {
99
101
self . attributes
100
- . borrow ( )
102
+ . read ( )
103
+ . unwrap ( )
101
104
. get ( "__qualname__" )
102
105
. cloned ( )
103
106
. unwrap_or_else ( || vm. ctx . new_str ( self . name . clone ( ) ) )
@@ -107,7 +110,8 @@ impl PyClassRef {
107
110
fn module ( self , vm : & VirtualMachine ) -> PyObjectRef {
108
111
// TODO: Implement getting the actual module a builtin type is from
109
112
self . attributes
110
- . borrow ( )
113
+ . read ( )
114
+ . unwrap ( )
111
115
. get ( "__module__" )
112
116
. cloned ( )
113
117
. unwrap_or_else ( || vm. ctx . new_str ( "builtins" . to_owned ( ) ) )
@@ -116,7 +120,8 @@ impl PyClassRef {
116
120
#[ pyproperty( magic, setter) ]
117
121
fn set_module ( self , value : PyObjectRef ) {
118
122
self . attributes
119
- . borrow_mut ( )
123
+ . write ( )
124
+ . unwrap ( )
120
125
. insert ( "__module__" . to_owned ( ) , value) ;
121
126
}
122
127
@@ -145,7 +150,7 @@ impl PyClassRef {
145
150
146
151
if let Some ( attr) = self . get_attr ( & name) {
147
152
let attr_class = attr. class ( ) ;
148
- let slots = attr_class. slots . borrow ( ) ;
153
+ let slots = attr_class. slots . read ( ) . unwrap ( ) ;
149
154
if let Some ( ref descr_get) = slots. descr_get {
150
155
return descr_get ( vm, attr, None , OptionalArg :: Present ( self . into_object ( ) ) ) ;
151
156
} else if let Some ( ref descriptor) = attr_class. get_attr ( "__get__" ) {
@@ -180,7 +185,8 @@ impl PyClassRef {
180
185
}
181
186
182
187
self . attributes
183
- . borrow_mut ( )
188
+ . write ( )
189
+ . unwrap ( )
184
190
. insert ( attr_name. to_string ( ) , value) ;
185
191
Ok ( ( ) )
186
192
}
@@ -196,7 +202,7 @@ impl PyClassRef {
196
202
}
197
203
198
204
if self . get_attr ( attr_name. as_str ( ) ) . is_some ( ) {
199
- self . attributes . borrow_mut ( ) . remove ( attr_name. as_str ( ) ) ;
205
+ self . attributes . write ( ) . unwrap ( ) . remove ( attr_name. as_str ( ) ) ;
200
206
Ok ( ( ) )
201
207
} else {
202
208
Err ( vm. new_attribute_error ( attr_name. as_str ( ) . to_owned ( ) ) )
@@ -206,13 +212,14 @@ impl PyClassRef {
206
212
// This is used for class initialisation where the vm is not yet available.
207
213
pub fn set_str_attr < V : Into < PyObjectRef > > ( & self , attr_name : & str , value : V ) {
208
214
self . attributes
209
- . borrow_mut ( )
215
+ . write ( )
216
+ . unwrap ( )
210
217
. insert ( attr_name. to_owned ( ) , value. into ( ) ) ;
211
218
}
212
219
213
220
#[ pymethod( magic) ]
214
221
fn subclasses ( self ) -> PyList {
215
- let mut subclasses = self . subclasses . borrow_mut ( ) ;
222
+ let mut subclasses = self . subclasses . write ( ) . unwrap ( ) ;
216
223
subclasses. retain ( |x| x. upgrade ( ) . is_some ( ) ) ;
217
224
PyList :: from (
218
225
subclasses
@@ -269,7 +276,7 @@ impl PyClassRef {
269
276
// Search the bases for the proper metatype to deal with this:
270
277
let winner = calculate_meta_class ( metatype. clone ( ) , & bases, vm) ?;
271
278
let metatype = if !winner. is ( & metatype) {
272
- if let Some ( ref tp_new) = winner. clone ( ) . slots . borrow ( ) . new {
279
+ if let Some ( ref tp_new) = winner. clone ( ) . slots . read ( ) . unwrap ( ) . new {
273
280
// Pass it to the winner
274
281
275
282
return tp_new ( vm, args. insert ( winner. into_object ( ) ) ) ;
@@ -294,10 +301,10 @@ impl PyClassRef {
294
301
let typ = new ( metatype, name. as_str ( ) , base. clone ( ) , bases, attributes)
295
302
. map_err ( |e| vm. new_type_error ( e) ) ?;
296
303
297
- typ. slots . borrow_mut ( ) . flags = base. slots . borrow ( ) . flags ;
304
+ typ. slots . write ( ) . unwrap ( ) . flags = base. slots . read ( ) . unwrap ( ) . flags ;
298
305
vm. ctx . add_tp_new_wrapper ( & typ) ;
299
306
300
- for ( name, obj) in typ. attributes . borrow ( ) . iter ( ) {
307
+ for ( name, obj) in typ. attributes . read ( ) . unwrap ( ) . clone ( ) . iter ( ) {
301
308
if let Some ( meth) = vm. get_method ( obj. clone ( ) , "__set_name__" ) {
302
309
let set_name = meth?;
303
310
vm. invoke (
@@ -393,9 +400,9 @@ fn call_tp_new(
393
400
let class_with_new_slot = typ
394
401
. iter_mro ( )
395
402
. cloned ( )
396
- . find ( |cls| cls. slots . borrow ( ) . new . is_some ( ) )
403
+ . find ( |cls| cls. slots . read ( ) . unwrap ( ) . new . is_some ( ) )
397
404
. expect ( "Should be able to find a new slot somewhere in the mro" ) ;
398
- let slots = class_with_new_slot. slots . borrow ( ) ;
405
+ let slots = class_with_new_slot. slots . read ( ) . unwrap ( ) ;
399
406
let new_slot = slots. new . as_ref ( ) . unwrap ( ) ;
400
407
new_slot ( vm, args. insert ( subtype. into_object ( ) ) )
401
408
}
@@ -422,7 +429,8 @@ impl PyClassRef {
422
429
flame_guard ! ( format!( "class_get_attr({:?})" , attr_name) ) ;
423
430
424
431
self . attributes
425
- . borrow ( )
432
+ . read ( )
433
+ . unwrap ( )
426
434
. get ( attr_name)
427
435
. cloned ( )
428
436
. or_else ( || self . get_super_attr ( attr_name) )
@@ -431,21 +439,21 @@ impl PyClassRef {
431
439
pub fn get_super_attr ( & self , attr_name : & str ) -> Option < PyObjectRef > {
432
440
self . mro
433
441
. iter ( )
434
- . find_map ( |class| class. attributes . borrow ( ) . get ( attr_name) . cloned ( ) )
442
+ . find_map ( |class| class. attributes . read ( ) . unwrap ( ) . get ( attr_name) . cloned ( ) )
435
443
}
436
444
437
445
// This is the internal has_attr implementation for fast lookup on a class.
438
446
pub fn has_attr ( & self , attr_name : & str ) -> bool {
439
447
self . iter_mro ( )
440
- . any ( |c| c. attributes . borrow ( ) . contains_key ( attr_name) )
448
+ . any ( |c| c. attributes . read ( ) . unwrap ( ) . contains_key ( attr_name) )
441
449
}
442
450
443
451
pub fn get_attributes ( self ) -> PyAttributes {
444
452
// Gather all members here:
445
453
let mut attributes = PyAttributes :: new ( ) ;
446
454
447
455
for bc in self . iter_mro ( ) . rev ( ) {
448
- for ( name, value) in bc. attributes . borrow ( ) . iter ( ) {
456
+ for ( name, value) in bc. attributes . read ( ) . unwrap ( ) . clone ( ) . iter ( ) {
449
457
attributes. insert ( name. to_owned ( ) , value. clone ( ) ) ;
450
458
}
451
459
}
@@ -540,9 +548,9 @@ pub fn new(
540
548
name : String :: from ( name) ,
541
549
bases,
542
550
mro,
543
- subclasses : RefCell :: default ( ) ,
544
- attributes : RefCell :: new ( dict) ,
545
- slots : RefCell :: default ( ) ,
551
+ subclasses : RwLock :: default ( ) ,
552
+ attributes : RwLock :: new ( dict) ,
553
+ slots : RwLock :: default ( ) ,
546
554
} ,
547
555
dict : None ,
548
556
typ : typ. into_typed_pyobj ( ) ,
@@ -553,7 +561,8 @@ pub fn new(
553
561
554
562
for base in & new_type. bases {
555
563
base. subclasses
556
- . borrow_mut ( )
564
+ . write ( )
565
+ . unwrap ( )
557
566
. push ( PyWeak :: downgrade ( new_type. as_object ( ) ) ) ;
558
567
}
559
568
@@ -603,7 +612,13 @@ fn best_base<'a>(bases: &'a [PyClassRef], vm: &VirtualMachine) -> PyResult<PyCla
603
612
// return NULL;
604
613
// }
605
614
606
- if !base_i. slots . borrow ( ) . flags . has_feature ( PyTpFlags :: BASETYPE ) {
615
+ if !base_i
616
+ . slots
617
+ . read ( )
618
+ . unwrap ( )
619
+ . flags
620
+ . has_feature ( PyTpFlags :: BASETYPE )
621
+ {
607
622
return Err ( vm. new_type_error ( format ! (
608
623
"type '{}' is not an acceptable base type" ,
609
624
base_i. name
0 commit comments