3838use core:: cell:: { Cell , UnsafeCell } ;
3939use core:: mem:: { self , ManuallyDrop } ;
4040use core:: num:: Wrapping ;
41- use core:: ptr;
41+ use core:: { ptr, fmt } ;
4242use core:: sync:: atomic;
4343use core:: sync:: atomic:: Ordering ;
4444
45- use arrayvec:: ArrayVec ;
4645use crossbeam_utils:: CachePadded ;
4746
4847use atomic:: { Shared , Owned } ;
@@ -60,10 +59,10 @@ const MAX_OBJECTS: usize = 64;
6059const MAX_OBJECTS : usize = 4 ;
6160
6261/// A bag of deferred functions.
63- #[ derive( Default , Debug ) ]
6462pub struct Bag {
6563 /// Stashed objects.
66- deferreds : ArrayVec < [ Deferred ; MAX_OBJECTS ] > ,
64+ deferreds : [ Deferred ; MAX_OBJECTS ] ,
65+ len : usize
6766}
6867
6968/// `Bag::try_push()` requires that it is safe for another thread to execute the given functions.
@@ -77,7 +76,7 @@ impl Bag {
7776
7877 /// Returns `true` if the bag is empty.
7978 pub fn is_empty ( & self ) -> bool {
80- self . deferreds . is_empty ( )
79+ self . len == 0
8180 }
8281
8382 /// Attempts to insert a deferred function into the bag.
@@ -89,7 +88,13 @@ impl Bag {
8988 ///
9089 /// It should be safe for another thread to execute the given function.
9190 pub unsafe fn try_push ( & mut self , deferred : Deferred ) -> Result < ( ) , Deferred > {
92- self . deferreds . try_push ( deferred) . map_err ( |e| e. element ( ) )
91+ if self . len < MAX_OBJECTS {
92+ self . deferreds [ self . len ] = deferred;
93+ self . len += 1 ;
94+ Ok ( ( ) )
95+ } else {
96+ Err ( deferred)
97+ }
9398 }
9499
95100 /// Seals the bag with the given epoch.
@@ -98,15 +103,53 @@ impl Bag {
98103 }
99104}
100105
106+ impl Default for Bag {
107+ fn default ( ) -> Self {
108+ // TODO: [no_op; MAX_OBJECTS] syntax blocked by https://github.com/rust-lang/rust/issues/49147
109+ #[ cfg( not( feature = "sanitize" ) ) ]
110+ return Bag { len : 0 , deferreds :
111+ [ Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) ,
112+ Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) ,
113+ Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) ,
114+ Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) ,
115+ Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) ,
116+ Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) ,
117+ Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) ,
118+ Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) ,
119+ Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) ,
120+ Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) ,
121+ Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) ,
122+ Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) ,
123+ Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) ,
124+ Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) ,
125+ Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) ,
126+ Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) ]
127+ } ;
128+ #[ cfg( feature = "sanitize" ) ]
129+ return Bag { len : 0 , deferreds : [ Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) , Deferred :: new ( no_op_func) ] } ;
130+ }
131+ }
132+
101133impl Drop for Bag {
102134 fn drop ( & mut self ) {
103135 // Call all deferred functions.
104- for deferred in self . deferreds . drain ( ..) {
136+ for i in 0 ..self . len {
137+ let no_op = Deferred :: new ( no_op_func) ;
138+ let deferred = mem:: replace ( & mut self . deferreds [ i] , no_op) ;
105139 deferred. call ( ) ;
106140 }
107141 }
108142}
109143
144+ // can't #[derive(Debug)] because Debug is not implemented for arrays 64 items long
145+ impl fmt:: Debug for Bag {
146+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
147+ f. debug_struct ( "Bag" ) . field ( "deferreds" , & & self . deferreds [ ..self . len ] ) . finish ( )
148+ }
149+ }
150+
151+ fn no_op_func ( ) { }
152+
110153/// A pair of an epoch and a bag.
111154#[ derive( Default , Debug ) ]
112155struct SealedBag {
0 commit comments