@@ -21,8 +21,21 @@ pub(crate) trait LazyInit {
2121 ///
2222 /// It might be called more than once per LazyBox, as multiple threads
2323 /// might race to initialize it concurrently, each constructing and initializing
24- /// their own box. ( All but one of them will be destroyed right after.)
24+ /// their own box. All but one of them will be passed to `cancel_init` right after.
2525 fn init ( ) -> Box < Self > ;
26+
27+ /// Any surplus boxes from `init()` that lost the initialization race
28+ /// are passed to this function for disposal.
29+ ///
30+ /// The default implementation calls destroy().
31+ fn cancel_init ( x : Box < Self > ) {
32+ Self :: destroy ( x) ;
33+ }
34+
35+ /// This is called to destroy a used box.
36+ ///
37+ /// The default implementation just drops it.
38+ fn destroy ( _: Box < Self > ) { }
2639}
2740
2841impl < T : LazyInit > LazyBox < T > {
@@ -45,7 +58,7 @@ impl<T: LazyInit> LazyBox<T> {
4558 Err ( ptr) => {
4659 // Lost the race to another thread.
4760 // Drop the box we created, and use the one from the other thread instead.
48- drop ( unsafe { Box :: from_raw ( new_ptr) } ) ;
61+ T :: cancel_init ( unsafe { Box :: from_raw ( new_ptr) } ) ;
4962 ptr
5063 }
5164 }
@@ -71,7 +84,7 @@ impl<T: LazyInit> Drop for LazyBox<T> {
7184 fn drop ( & mut self ) {
7285 let ptr = * self . ptr . get_mut ( ) ;
7386 if !ptr. is_null ( ) {
74- drop ( unsafe { Box :: from_raw ( ptr) } ) ;
87+ T :: destroy ( unsafe { Box :: from_raw ( ptr) } ) ;
7588 }
7689 }
7790}
0 commit comments