1
1
use std:: cell:: UnsafeCell ;
2
2
use std:: collections:: { hash_map, VecDeque } ;
3
3
use std:: mem:: { ManuallyDrop , MaybeUninit } ;
4
- use std:: sync:: atomic:: { AtomicI64 , AtomicU8 , Ordering } ;
5
- use std:: sync:: { Arc , Weak } ;
4
+ use std:: sync:: atomic:: { AtomicI64 , Ordering } ;
5
+ use std:: sync:: { Arc , Once , Weak } ;
6
6
7
7
use anyhow:: { Context , Result } ;
8
8
use bumpalo:: Bump ;
@@ -632,19 +632,14 @@ pub struct StorageCell {
632
632
cell_storage : Arc < CellStorage > ,
633
633
descriptor : CellDescriptor ,
634
634
bit_len : u16 ,
635
- data : Vec < u8 > ,
636
- hashes : Vec < ( HashBytes , u16 ) > ,
635
+ data : Box < [ u8 ] > ,
636
+ hashes : Box < [ ( HashBytes , u16 ) ] > ,
637
637
638
- reference_states : [ AtomicU8 ; 4 ] ,
638
+ reference_states : [ Once ; 4 ] ,
639
639
reference_data : [ UnsafeCell < StorageCellReferenceData > ; 4 ] ,
640
640
}
641
641
642
642
impl StorageCell {
643
- const REF_EMPTY : u8 = 0x0 ;
644
- const REF_RUNNING : u8 = 0x1 ;
645
- const REF_STORAGE : u8 = 0x2 ;
646
- const REF_REPLACED : u8 = 0x3 ;
647
-
648
643
pub fn deserialize ( cell_storage : Arc < CellStorage > , buffer : & [ u8 ] ) -> Option < Self > {
649
644
if buffer. len ( ) < 4 {
650
645
return None ;
@@ -661,9 +656,11 @@ impl StorageCell {
661
656
return None ;
662
657
}
663
658
664
- let data = buffer[ 4 ..4 + byte_len] . to_vec ( ) ;
659
+ let data = Box :: from ( & buffer[ 4 ..4 + byte_len] ) ;
660
+
661
+ let mut hashes = Vec :: new ( ) ;
662
+ hashes. reserve_exact ( hash_count) ;
665
663
666
- let mut hashes = Vec :: with_capacity ( hash_count) ;
667
664
let mut offset = 4 + byte_len;
668
665
for _ in 0 ..hash_count {
669
666
hashes. push ( (
@@ -673,7 +670,7 @@ impl StorageCell {
673
670
offset += 32 + 2 ;
674
671
}
675
672
676
- let reference_states = Default :: default ( ) ;
673
+ let reference_states = [ ( ) ; 4 ] . map ( |_| Once :: new ( ) ) ;
677
674
let reference_data = unsafe {
678
675
MaybeUninit :: < [ UnsafeCell < StorageCellReferenceData > ; 4 ] > :: uninit ( ) . assume_init ( )
679
676
} ;
@@ -689,7 +686,7 @@ impl StorageCell {
689
686
bit_len,
690
687
descriptor,
691
688
data,
692
- hashes,
689
+ hashes : hashes . into_boxed_slice ( ) ,
693
690
reference_states,
694
691
reference_data,
695
692
} )
@@ -767,88 +764,22 @@ impl StorageCell {
767
764
return None ;
768
765
}
769
766
770
- let state = & self . reference_states [ index as usize ] ;
771
767
let slot = self . reference_data [ index as usize ] . get ( ) ;
768
+ self . reference_states [ index as usize ] . call_once ( || {
769
+ let cell = self
770
+ . cell_storage
771
+ . load_cell ( unsafe { ( * slot) . hash } )
772
+ . unwrap ( ) ;
772
773
773
- let current_state = state. load ( Ordering :: Acquire ) ;
774
- if current_state == Self :: REF_STORAGE {
775
- return Some ( unsafe { & ( * slot) . storage_cell } ) ;
776
- }
777
-
778
- let mut res = Ok ( ( ) ) ;
779
- Self :: initialize_inner ( state, & mut || match self
780
- . cell_storage
781
- . load_cell ( unsafe { ( * slot) . hash } )
782
- {
783
- Ok ( cell) => unsafe {
774
+ unsafe {
784
775
* slot = StorageCellReferenceData {
785
776
storage_cell : ManuallyDrop :: new ( cell) ,
786
- } ;
787
- true
788
- } ,
789
- Err ( err) => {
790
- res = Err ( err) ;
791
- false
792
- }
777
+ }
778
+ } ;
793
779
} ) ;
794
780
795
- // TODO: just return none?
796
- res. unwrap ( ) ;
797
-
798
781
Some ( unsafe { & ( * slot) . storage_cell } )
799
782
}
800
-
801
- fn initialize_inner ( state : & AtomicU8 , init : & mut impl FnMut ( ) -> bool ) {
802
- struct Guard < ' a > {
803
- state : & ' a AtomicU8 ,
804
- new_state : u8 ,
805
- }
806
-
807
- impl Drop for Guard < ' _ > {
808
- fn drop ( & mut self ) {
809
- self . state . store ( self . new_state , Ordering :: Release ) ;
810
- unsafe {
811
- let key = self . state as * const AtomicU8 as usize ;
812
- parking_lot_core:: unpark_all ( key, parking_lot_core:: DEFAULT_UNPARK_TOKEN ) ;
813
- }
814
- }
815
- }
816
-
817
- loop {
818
- let exchange = state. compare_exchange_weak (
819
- Self :: REF_EMPTY ,
820
- Self :: REF_RUNNING ,
821
- Ordering :: Acquire ,
822
- Ordering :: Acquire ,
823
- ) ;
824
- match exchange {
825
- Ok ( _) => {
826
- let mut guard = Guard {
827
- state,
828
- new_state : Self :: REF_EMPTY ,
829
- } ;
830
- if init ( ) {
831
- guard. new_state = Self :: REF_STORAGE ;
832
- }
833
- return ;
834
- }
835
- Err ( Self :: REF_STORAGE ) => return ,
836
- Err ( Self :: REF_RUNNING ) => unsafe {
837
- let key = state as * const AtomicU8 as usize ;
838
- parking_lot_core:: park (
839
- key,
840
- || state. load ( Ordering :: Relaxed ) == Self :: REF_RUNNING ,
841
- || ( ) ,
842
- |_, _| ( ) ,
843
- parking_lot_core:: DEFAULT_PARK_TOKEN ,
844
- None ,
845
- ) ;
846
- } ,
847
- Err ( Self :: REF_EMPTY ) => ( ) ,
848
- Err ( _) => debug_assert ! ( false ) ,
849
- }
850
- }
851
- }
852
783
}
853
784
854
785
impl CellImpl for StorageCell {
@@ -892,48 +823,14 @@ impl CellImpl for StorageCell {
892
823
}
893
824
894
825
fn take_first_child ( & mut self ) -> Option < Cell > {
895
- let state = self . reference_states [ 0 ] . swap ( Self :: REF_EMPTY , Ordering :: AcqRel ) ;
896
- let data = self . reference_data [ 0 ] . get_mut ( ) ;
897
- match state {
898
- Self :: REF_STORAGE => Some ( unsafe { data. take_storage_cell ( ) } ) ,
899
- Self :: REF_REPLACED => Some ( unsafe { data. take_replaced_cell ( ) } ) ,
900
- _ => None ,
901
- }
826
+ None
902
827
}
903
828
904
829
fn replace_first_child ( & mut self , parent : Cell ) -> std:: result:: Result < Cell , Cell > {
905
- let state = self . reference_states [ 0 ] . load ( Ordering :: Acquire ) ;
906
- if state < Self :: REF_STORAGE {
907
- return Err ( parent) ;
908
- }
909
-
910
- self . reference_states [ 0 ] . store ( Self :: REF_REPLACED , Ordering :: Release ) ;
911
- let data = self . reference_data [ 0 ] . get_mut ( ) ;
912
-
913
- let cell = match state {
914
- Self :: REF_STORAGE => unsafe { data. take_storage_cell ( ) } ,
915
- Self :: REF_REPLACED => unsafe { data. take_replaced_cell ( ) } ,
916
- _ => return Err ( parent) ,
917
- } ;
918
- data. replaced_cell = ManuallyDrop :: new ( parent) ;
919
- Ok ( cell)
830
+ Err ( parent)
920
831
}
921
832
922
833
fn take_next_child ( & mut self ) -> Option < Cell > {
923
- while self . descriptor . reference_count ( ) > 1 {
924
- self . descriptor . d1 -= 1 ;
925
- let idx = ( self . descriptor . d1 & CellDescriptor :: REF_COUNT_MASK ) as usize ;
926
-
927
- let state = self . reference_states [ idx] . swap ( Self :: REF_EMPTY , Ordering :: AcqRel ) ;
928
- let data = self . reference_data [ idx] . get_mut ( ) ;
929
-
930
- return Some ( match state {
931
- Self :: REF_STORAGE => unsafe { data. take_storage_cell ( ) } ,
932
- Self :: REF_REPLACED => unsafe { data. take_replaced_cell ( ) } ,
933
- _ => continue ,
934
- } ) ;
935
- }
936
-
937
834
None
938
835
}
939
836
@@ -948,16 +845,13 @@ impl CellImpl for StorageCell {
948
845
impl Drop for StorageCell {
949
846
fn drop ( & mut self ) {
950
847
self . cell_storage . drop_cell ( DynCell :: repr_hash ( self ) ) ;
848
+
951
849
for i in 0 ..4 {
952
- let state = self . reference_states [ i] . load ( Ordering :: Acquire ) ;
850
+ let initialized = self . reference_states [ i] . is_completed ( ) ;
953
851
let data = self . reference_data [ i] . get_mut ( ) ;
954
852
955
- unsafe {
956
- match state {
957
- Self :: REF_STORAGE => ManuallyDrop :: drop ( & mut data. storage_cell ) ,
958
- Self :: REF_REPLACED => ManuallyDrop :: drop ( & mut data. replaced_cell ) ,
959
- _ => { }
960
- }
853
+ if initialized {
854
+ unsafe { ManuallyDrop :: drop ( & mut data. storage_cell ) }
961
855
}
962
856
}
963
857
}
@@ -967,22 +861,10 @@ unsafe impl Send for StorageCell {}
967
861
unsafe impl Sync for StorageCell { }
968
862
969
863
pub union StorageCellReferenceData {
970
- /// Incplmete state.
864
+ /// Incomplete state.
971
865
hash : HashBytes ,
972
866
/// Complete state.
973
867
storage_cell : ManuallyDrop < Arc < StorageCell > > ,
974
- /// Replaced state.
975
- replaced_cell : ManuallyDrop < Cell > ,
976
- }
977
-
978
- impl StorageCellReferenceData {
979
- unsafe fn take_storage_cell ( & mut self ) -> Cell {
980
- Cell :: from ( ManuallyDrop :: take ( & mut self . storage_cell ) as Arc < _ > )
981
- }
982
-
983
- unsafe fn take_replaced_cell ( & mut self ) -> Cell {
984
- ManuallyDrop :: take ( & mut self . replaced_cell )
985
- }
986
868
}
987
869
988
870
struct RawCellsCache ( Cache < HashBytes , RawCellsCacheItem , CellSizeEstimator , FastHasherState > ) ;
0 commit comments