@@ -14,6 +14,10 @@ use core::{
1414#[ cfg( feature = "atomic_append" ) ]
1515use core:: sync:: atomic:: { AtomicUsize , Ordering } ;
1616
17+ /// A closure that becomes called when a `HeaderVec` becomes reallocated.
18+ /// This is closure is responsible for updating weak nodes.
19+ pub type WeakFixupFn < ' a > = & ' a mut dyn FnMut ( * const ( ) ) ;
20+
1721struct HeaderVecHeader < H > {
1822 head : H ,
1923 capacity : usize ,
@@ -220,39 +224,72 @@ impl<H, T> HeaderVec<H, T> {
220224 }
221225
222226 /// Reserves capacity for at least `additional` more elements to be inserted in the given `HeaderVec`.
223- #[ inline( always) ]
224- pub fn reserve ( & mut self , additional : usize ) -> Option < * const ( ) > {
225- if self . spare_capacity ( ) < additional {
226- let len = self . len_exact ( ) ;
227- unsafe { self . resize_cold ( len. saturating_add ( additional) , false ) }
228- } else {
229- None
230- }
227+ #[ inline]
228+ pub fn reserve ( & mut self , additional : usize ) {
229+ self . reserve_intern ( additional, false , None ) ;
230+ }
231+
232+ /// Reserves capacity for at least `additional` more elements to be inserted in the given `HeaderVec`.
233+ /// This method must be used when `HeaderVecWeak` are used. It takes a closure that is responsible for
234+ /// updating the weak references as additional parameter.
235+ #[ inline]
236+ pub fn reserve_with_weakfix ( & mut self , additional : usize , weak_fixup : WeakFixupFn ) {
237+ self . reserve_intern ( additional, false , Some ( weak_fixup) ) ;
238+ }
239+
240+ /// Reserves capacity for exactly `additional` more elements to be inserted in the given `HeaderVec`.
241+ #[ inline]
242+ pub fn reserve_exact ( & mut self , additional : usize ) {
243+ self . reserve_intern ( additional, true , None ) ;
231244 }
232245
233246 /// Reserves capacity for exactly `additional` more elements to be inserted in the given `HeaderVec`.
247+ /// This method must be used when `HeaderVecWeak` are used. It takes a closure that is responsible for
248+ /// updating the weak references as additional parameter.
234249 #[ inline]
235- pub fn reserve_exact ( & mut self , additional : usize ) -> Option < * const ( ) > {
250+ pub fn reserve_exact_with_weakfix ( & mut self , additional : usize , weak_fixup : WeakFixupFn ) {
251+ self . reserve_intern ( additional, true , Some ( weak_fixup) ) ;
252+ }
253+
254+ /// Reserves capacity for at least `additional` more elements to be inserted in the given `HeaderVec`.
255+ #[ inline( always) ]
256+ fn reserve_intern ( & mut self , additional : usize , exact : bool , weak_fixup : Option < WeakFixupFn > ) {
236257 if self . spare_capacity ( ) < additional {
237258 let len = self . len_exact ( ) ;
238- unsafe { self . resize_cold ( len . saturating_add ( additional ) , true ) }
239- } else {
240- None
259+ // using saturating_add here ensures that we get a allocation error instead wrapping over and
260+ // allocating a total wrong size
261+ unsafe { self . resize_cold ( len . saturating_add ( additional ) , exact , weak_fixup ) } ;
241262 }
242263 }
243264
244265 /// Shrinks the capacity of the `HeaderVec` to the `min_capacity` or `self.len()`, whichever is larger.
245266 #[ inline]
246- pub fn shrink_to ( & mut self , min_capacity : usize ) -> Option < * const ( ) > {
267+ pub fn shrink_to ( & mut self , min_capacity : usize ) {
247268 let requested_capacity = self . len_exact ( ) . max ( min_capacity) ;
248- unsafe { self . resize_cold ( requested_capacity, true ) }
269+ unsafe { self . resize_cold ( requested_capacity, true , None ) } ;
270+ }
271+
272+ /// Shrinks the capacity of the `HeaderVec` to the `min_capacity` or `self.len()`, whichever is larger.
273+ /// This method must be used when `HeaderVecWeak` are used. It takes a closure that is responsible for
274+ /// updating the weak references as additional parameter.
275+ #[ inline]
276+ pub fn shrink_to_with_weakfix ( & mut self , min_capacity : usize , weak_fixup : WeakFixupFn ) {
277+ let requested_capacity = self . len_exact ( ) . max ( min_capacity) ;
278+ unsafe { self . resize_cold ( requested_capacity, true , Some ( weak_fixup) ) } ;
279+ }
280+
281+ /// Resizes the vector hold exactly `self.len()` elements.
282+ #[ inline( always) ]
283+ pub fn shrink_to_fit ( & mut self ) {
284+ self . shrink_to ( 0 ) ;
249285 }
250286
251287 /// Resizes the vector hold exactly `self.len()` elements.
288+ /// This method must be used when `HeaderVecWeak` are used. It takes a closure that is responsible for
289+ /// updating the weak references as additional parameter.
252290 #[ inline( always) ]
253- pub fn shrink_to_fit ( & mut self ) -> Option < * const ( ) > {
254- let len = self . len_exact ( ) ;
255- self . shrink_to ( len)
291+ pub fn shrink_to_fit_with_weakfix ( & mut self , weak_fixup : WeakFixupFn ) {
292+ self . shrink_to_with_weakfix ( 0 , weak_fixup) ;
256293 }
257294
258295 /// Resize the vector to least `requested_capacity` elements.
@@ -264,7 +301,12 @@ impl<H, T> HeaderVec<H, T> {
264301 ///
265302 /// `requested_capacity` must be greater or equal than `self.len()`
266303 #[ cold]
267- unsafe fn resize_cold ( & mut self , requested_capacity : usize , exact : bool ) -> Option < * const ( ) > {
304+ unsafe fn resize_cold (
305+ & mut self ,
306+ requested_capacity : usize ,
307+ exact : bool ,
308+ weak_fixup : Option < WeakFixupFn > ,
309+ ) {
268310 // For efficiency we do only a debug_assert here, this is a internal unsafe function
269311 // it's contract should be already enforced by the caller which is under our control
270312 debug_assert ! (
@@ -275,7 +317,7 @@ impl<H, T> HeaderVec<H, T> {
275317
276318 // Shortcut when nothing is to be done.
277319 if requested_capacity == old_capacity {
278- return None ;
320+ return ;
279321 }
280322
281323 let new_capacity = if requested_capacity > old_capacity {
@@ -319,7 +361,7 @@ impl<H, T> HeaderVec<H, T> {
319361
320362 // Check if the new pointer is different than the old one.
321363 let previous_pointer = if ptr != self . ptr {
322- // Give the user the old pointer so they can update everything .
364+ // Store old pointer for weak_fixup .
323365 Some ( self . ptr ( ) )
324366 } else {
325367 None
@@ -329,7 +371,8 @@ impl<H, T> HeaderVec<H, T> {
329371 // And set the new capacity.
330372 self . header_mut ( ) . capacity = new_capacity;
331373
332- previous_pointer
374+ // Finally run the weak_fixup closure when provided
375+ previous_pointer. map ( |ptr| weak_fixup. map ( |weak_fixup| weak_fixup ( ptr) ) ) ;
333376 }
334377
335378 /// Adds an item to the end of the list.
@@ -344,7 +387,7 @@ impl<H, T> HeaderVec<H, T> {
344387 core:: ptr:: write ( self . as_mut_ptr ( ) . add ( old_len) , item) ;
345388 }
346389 self . header_mut ( ) . len = new_len. into ( ) ;
347- previous_pointer
390+ todo ! ( "weak_fixup transformartion" ) // previous_pointer
348391 }
349392
350393 /// Retains only the elements specified by the predicate.
@@ -497,7 +540,7 @@ impl<H, T: Clone> HeaderVec<H, T> {
497540 // correct the len
498541 self . header_mut ( ) . len = ( self . len_exact ( ) + slice. len ( ) ) . into ( ) ;
499542
500- previous_pointer
543+ todo ! ( "weak_fixup transformartion" ) // previous_pointer
501544 }
502545}
503546
0 commit comments