1- use std:: cell:: RefCell ;
21use std:: collections:: { HashMap , HashSet } ;
32use std:: fmt;
3+ use std:: sync:: RwLock ;
44
55use super :: objdict:: PyDictRef ;
66use super :: objlist:: PyList ;
@@ -12,7 +12,7 @@ use super::objweakref::PyWeak;
1212use crate :: function:: { OptionalArg , PyFuncArgs } ;
1313use crate :: pyobject:: {
1414 IdProtocol , PyAttributes , PyClassImpl , PyContext , PyIterable , PyObject , PyObjectRef , PyRef ,
15- PyResult , PyValue , TypeProtocol ,
15+ PyResult , PyValue , ThreadSafe , TypeProtocol ,
1616} ;
1717use crate :: slots:: { PyClassSlots , PyTpFlags } ;
1818use crate :: vm:: VirtualMachine ;
@@ -27,11 +27,13 @@ pub struct PyClass {
2727 pub name : String ,
2828 pub bases : Vec < PyClassRef > ,
2929 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 > ,
3333}
3434
35+ impl ThreadSafe for PyClass { }
36+
3537impl fmt:: Display for PyClass {
3638 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
3739 fmt:: Display :: fmt ( & self . name , f)
@@ -97,7 +99,8 @@ impl PyClassRef {
9799 #[ pyproperty( magic) ]
98100 fn qualname ( self , vm : & VirtualMachine ) -> PyObjectRef {
99101 self . attributes
100- . borrow ( )
102+ . read ( )
103+ . unwrap ( )
101104 . get ( "__qualname__" )
102105 . cloned ( )
103106 . unwrap_or_else ( || vm. ctx . new_str ( self . name . clone ( ) ) )
@@ -107,7 +110,8 @@ impl PyClassRef {
107110 fn module ( self , vm : & VirtualMachine ) -> PyObjectRef {
108111 // TODO: Implement getting the actual module a builtin type is from
109112 self . attributes
110- . borrow ( )
113+ . read ( )
114+ . unwrap ( )
111115 . get ( "__module__" )
112116 . cloned ( )
113117 . unwrap_or_else ( || vm. ctx . new_str ( "builtins" . to_owned ( ) ) )
@@ -116,7 +120,8 @@ impl PyClassRef {
116120 #[ pyproperty( magic, setter) ]
117121 fn set_module ( self , value : PyObjectRef ) {
118122 self . attributes
119- . borrow_mut ( )
123+ . write ( )
124+ . unwrap ( )
120125 . insert ( "__module__" . to_owned ( ) , value) ;
121126 }
122127
@@ -145,7 +150,7 @@ impl PyClassRef {
145150
146151 if let Some ( attr) = self . get_attr ( & name) {
147152 let attr_class = attr. class ( ) ;
148- let slots = attr_class. slots . borrow ( ) ;
153+ let slots = attr_class. slots . read ( ) . unwrap ( ) ;
149154 if let Some ( ref descr_get) = slots. descr_get {
150155 return descr_get ( vm, attr, None , OptionalArg :: Present ( self . into_object ( ) ) ) ;
151156 } else if let Some ( ref descriptor) = attr_class. get_attr ( "__get__" ) {
@@ -180,7 +185,8 @@ impl PyClassRef {
180185 }
181186
182187 self . attributes
183- . borrow_mut ( )
188+ . write ( )
189+ . unwrap ( )
184190 . insert ( attr_name. to_string ( ) , value) ;
185191 Ok ( ( ) )
186192 }
@@ -196,7 +202,7 @@ impl PyClassRef {
196202 }
197203
198204 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 ( ) ) ;
200206 Ok ( ( ) )
201207 } else {
202208 Err ( vm. new_attribute_error ( attr_name. as_str ( ) . to_owned ( ) ) )
@@ -206,13 +212,14 @@ impl PyClassRef {
206212 // This is used for class initialisation where the vm is not yet available.
207213 pub fn set_str_attr < V : Into < PyObjectRef > > ( & self , attr_name : & str , value : V ) {
208214 self . attributes
209- . borrow_mut ( )
215+ . write ( )
216+ . unwrap ( )
210217 . insert ( attr_name. to_owned ( ) , value. into ( ) ) ;
211218 }
212219
213220 #[ pymethod( magic) ]
214221 fn subclasses ( self ) -> PyList {
215- let mut subclasses = self . subclasses . borrow_mut ( ) ;
222+ let mut subclasses = self . subclasses . write ( ) . unwrap ( ) ;
216223 subclasses. retain ( |x| x. upgrade ( ) . is_some ( ) ) ;
217224 PyList :: from (
218225 subclasses
@@ -269,7 +276,7 @@ impl PyClassRef {
269276 // Search the bases for the proper metatype to deal with this:
270277 let winner = calculate_meta_class ( metatype. clone ( ) , & bases, vm) ?;
271278 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 {
273280 // Pass it to the winner
274281
275282 return tp_new ( vm, args. insert ( winner. into_object ( ) ) ) ;
@@ -294,10 +301,10 @@ impl PyClassRef {
294301 let typ = new ( metatype, name. as_str ( ) , base. clone ( ) , bases, attributes)
295302 . map_err ( |e| vm. new_type_error ( e) ) ?;
296303
297- typ. slots . borrow_mut ( ) . flags = base. slots . borrow ( ) . flags ;
304+ typ. slots . write ( ) . unwrap ( ) . flags = base. slots . read ( ) . unwrap ( ) . flags ;
298305 vm. ctx . add_tp_new_wrapper ( & typ) ;
299306
300- for ( name, obj) in typ. attributes . borrow ( ) . iter ( ) {
307+ for ( name, obj) in typ. attributes . read ( ) . unwrap ( ) . clone ( ) . iter ( ) {
301308 if let Some ( meth) = vm. get_method ( obj. clone ( ) , "__set_name__" ) {
302309 let set_name = meth?;
303310 vm. invoke (
@@ -393,9 +400,9 @@ fn call_tp_new(
393400 let class_with_new_slot = typ
394401 . iter_mro ( )
395402 . cloned ( )
396- . find ( |cls| cls. slots . borrow ( ) . new . is_some ( ) )
403+ . find ( |cls| cls. slots . read ( ) . unwrap ( ) . new . is_some ( ) )
397404 . 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 ( ) ;
399406 let new_slot = slots. new . as_ref ( ) . unwrap ( ) ;
400407 new_slot ( vm, args. insert ( subtype. into_object ( ) ) )
401408}
@@ -422,7 +429,8 @@ impl PyClassRef {
422429 flame_guard ! ( format!( "class_get_attr({:?})" , attr_name) ) ;
423430
424431 self . attributes
425- . borrow ( )
432+ . read ( )
433+ . unwrap ( )
426434 . get ( attr_name)
427435 . cloned ( )
428436 . or_else ( || self . get_super_attr ( attr_name) )
@@ -431,21 +439,21 @@ impl PyClassRef {
431439 pub fn get_super_attr ( & self , attr_name : & str ) -> Option < PyObjectRef > {
432440 self . mro
433441 . iter ( )
434- . find_map ( |class| class. attributes . borrow ( ) . get ( attr_name) . cloned ( ) )
442+ . find_map ( |class| class. attributes . read ( ) . unwrap ( ) . get ( attr_name) . cloned ( ) )
435443 }
436444
437445 // This is the internal has_attr implementation for fast lookup on a class.
438446 pub fn has_attr ( & self , attr_name : & str ) -> bool {
439447 self . iter_mro ( )
440- . any ( |c| c. attributes . borrow ( ) . contains_key ( attr_name) )
448+ . any ( |c| c. attributes . read ( ) . unwrap ( ) . contains_key ( attr_name) )
441449 }
442450
443451 pub fn get_attributes ( self ) -> PyAttributes {
444452 // Gather all members here:
445453 let mut attributes = PyAttributes :: new ( ) ;
446454
447455 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 ( ) {
449457 attributes. insert ( name. to_owned ( ) , value. clone ( ) ) ;
450458 }
451459 }
@@ -540,9 +548,9 @@ pub fn new(
540548 name : String :: from ( name) ,
541549 bases,
542550 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 ( ) ,
546554 } ,
547555 dict : None ,
548556 typ : typ. into_typed_pyobj ( ) ,
@@ -553,7 +561,8 @@ pub fn new(
553561
554562 for base in & new_type. bases {
555563 base. subclasses
556- . borrow_mut ( )
564+ . write ( )
565+ . unwrap ( )
557566 . push ( PyWeak :: downgrade ( new_type. as_object ( ) ) ) ;
558567 }
559568
@@ -603,7 +612,13 @@ fn best_base<'a>(bases: &'a [PyClassRef], vm: &VirtualMachine) -> PyResult<PyCla
603612 // return NULL;
604613 // }
605614
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+ {
607622 return Err ( vm. new_type_error ( format ! (
608623 "type '{}' is not an acceptable base type" ,
609624 base_i. name
0 commit comments