@@ -21,8 +21,21 @@ pub(crate) trait LazyInit {
21
21
///
22
22
/// It might be called more than once per LazyBox, as multiple threads
23
23
/// 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.
25
25
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 > ) { }
26
39
}
27
40
28
41
impl < T : LazyInit > LazyBox < T > {
@@ -45,7 +58,7 @@ impl<T: LazyInit> LazyBox<T> {
45
58
Err ( ptr) => {
46
59
// Lost the race to another thread.
47
60
// 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) } ) ;
49
62
ptr
50
63
}
51
64
}
@@ -71,7 +84,7 @@ impl<T: LazyInit> Drop for LazyBox<T> {
71
84
fn drop ( & mut self ) {
72
85
let ptr = * self . ptr . get_mut ( ) ;
73
86
if !ptr. is_null ( ) {
74
- drop ( unsafe { Box :: from_raw ( ptr) } ) ;
87
+ T :: destroy ( unsafe { Box :: from_raw ( ptr) } ) ;
75
88
}
76
89
}
77
90
}
0 commit comments