@@ -20,7 +20,7 @@ use alloc::fmt;
2020use core:: mem:: size_of;
2121use core:: ops:: ControlFlow ;
2222use core:: sync:: atomic:: {
23- AtomicU32 , AtomicU64 ,
23+ AtomicU32 ,
2424 Ordering :: { AcqRel , Acquire , Relaxed , Release } ,
2525} ;
2626use num_traits:: ToPrimitive ;
@@ -39,7 +39,6 @@ type EntryIndex = usize;
3939
4040pub ( crate ) struct Dict < T = PyObjectRef > {
4141 inner : PyRwLock < DictInner < T > > ,
42- version : AtomicU64 ,
4342 /// Keys-version stamp, assigned lazily by `assign_keys_version` and
4443 /// reset to 0 whenever the key set changes. Value-only updates keep it.
4544 ///
@@ -202,7 +201,6 @@ impl<T: Clone> Clone for Dict<T> {
202201 fn clone ( & self ) -> Self {
203202 Self {
204203 inner : PyRwLock :: new ( self . inner . read ( ) . clone ( ) ) ,
205- version : AtomicU64 :: new ( 0 ) ,
206204 keys_version : AtomicU32 :: new ( 0 ) ,
207205 }
208206 }
@@ -217,7 +215,6 @@ impl<T> Default for Dict<T> {
217215 indices : vec ! [ IndexEntry :: FREE ; 8 ] ,
218216 entries : Vec :: new ( ) ,
219217 } ) ,
220- version : AtomicU64 :: new ( 0 ) ,
221218 keys_version : AtomicU32 :: new ( 0 ) ,
222219 }
223220 }
@@ -362,16 +359,6 @@ impl<T> DictInner<T> {
362359type PopInnerResult < T > = ControlFlow < Option < DictEntry < T > > > ;
363360
364361impl < T : Clone > Dict < T > {
365- /// Monotonically increasing version counter for mutation tracking.
366- pub ( crate ) fn version ( & self ) -> u64 {
367- self . version . load ( Acquire )
368- }
369-
370- /// Bump the version counter after any mutation.
371- fn bump_version ( & self ) {
372- self . version . fetch_add ( 1 , Release ) ;
373- }
374-
375362 /// Current keys-version stamp, or 0 if none has been assigned since the
376363 /// last key-set change. Equal nonzero stamps guarantee an unchanged key
377364 /// set (values may differ).
@@ -500,7 +487,6 @@ impl<T: Clone> Dict<T> {
500487 ) ]
501488 if entry. index == index_index {
502489 let removed = core:: mem:: replace ( & mut entry. value , value) ;
503- self . bump_version ( ) ;
504490 // defer dec RC
505491 break Some ( removed) ;
506492 } else {
@@ -517,7 +503,6 @@ impl<T: Clone> Dict<T> {
517503 }
518504 self . invalidate_keys_version ( ) ;
519505 inner. unchecked_push ( index_index, hash, key. to_pyobject ( vm) , value, entry_index) ;
520- self . bump_version ( ) ;
521506 break None ;
522507 }
523508 } ;
@@ -616,7 +601,6 @@ impl<T: Clone> Dict<T> {
616601 match inner. entries . get_mut ( hint) {
617602 Some ( Some ( entry) ) if key. key_is ( & entry. key ) => {
618603 let removed = core:: mem:: replace ( & mut entry. value , value) ;
619- self . bump_version ( ) ;
620604 drop ( inner) ;
621605 // defer dec RC until after the lock is released
622606 drop ( removed) ;
@@ -656,6 +640,22 @@ impl<T: Clone> Dict<T> {
656640 }
657641 }
658642
643+ /// Read an entry directly when a cached keys-version still describes the
644+ /// dictionary layout. The version is rechecked while holding the read lock
645+ /// so the entry index and value are observed from the same key-set state.
646+ #[ inline]
647+ pub ( crate ) fn get_index_if_keys_version ( & self , version : u32 , index : usize ) -> Option < T > {
648+ let inner = self . read ( ) ;
649+ if self . keys_version . load ( Acquire ) != version {
650+ return None ;
651+ }
652+ inner
653+ . entries
654+ . get ( index)
655+ . and_then ( Option :: as_ref)
656+ . map ( |entry| entry. value . clone ( ) )
657+ }
658+
659659 fn _get_inner < K : DictKey + ?Sized > (
660660 & self ,
661661 vm : & VirtualMachine ,
@@ -701,7 +701,6 @@ impl<T: Clone> Dict<T> {
701701 inner. indices . resize ( 8 , IndexEntry :: FREE ) ;
702702 inner. used = 0 ;
703703 inner. filled = 0 ;
704- self . bump_version ( ) ;
705704 // defer dec rc
706705 core:: mem:: take ( & mut inner. entries )
707706 } ;
@@ -830,7 +829,6 @@ impl<T: Clone> Dict<T> {
830829 }
831830 self . invalidate_keys_version ( ) ;
832831 inner. unchecked_push ( index_index, hash, key. to_owned ( ) , value, entry) ;
833- self . bump_version ( ) ;
834832 break None ;
835833 } ;
836834 Ok ( ( ) )
@@ -867,7 +865,6 @@ impl<T: Clone> Dict<T> {
867865 value. clone ( ) ,
868866 index_entry,
869867 ) ;
870- self . bump_version ( ) ;
871868 return Ok ( value) ;
872869 }
873870 }
@@ -905,7 +902,6 @@ impl<T: Clone> Dict<T> {
905902 let ret = ( key_obj. clone ( ) , value. clone ( ) ) ;
906903 self . invalidate_keys_version ( ) ;
907904 inner. unchecked_push ( index_index, hash, key_obj, value, index_entry) ;
908- self . bump_version ( ) ;
909905 return Ok ( ret) ;
910906 }
911907 }
@@ -1117,7 +1113,6 @@ impl<T: Clone> Dict<T> {
11171113 } = IndexEntry :: DUMMY ;
11181114 inner. used -= 1 ;
11191115 let removed = slot. take ( ) ;
1120- self . bump_version ( ) ;
11211116 Ok ( ControlFlow :: Break ( removed) )
11221117 }
11231118
@@ -1152,7 +1147,6 @@ impl<T: Clone> Dict<T> {
11521147 // entry.index always refers valid index
11531148 inner. indices . get_unchecked_mut ( entry. index )
11541149 } = IndexEntry :: DUMMY ;
1155- self . bump_version ( ) ;
11561150 Some ( ( entry. key , entry. value ) )
11571151 }
11581152
0 commit comments