diff --git a/tracing-core/src/spin/once.rs b/tracing-core/src/spin/once.rs index 219eb31540..8643d472b2 100644 --- a/tracing-core/src/spin/once.rs +++ b/tracing-core/src/spin/once.rs @@ -76,24 +76,32 @@ impl Once { let mut status = self.state.load(Ordering::SeqCst); if status == INCOMPLETE { - status = self - .state - .compare_and_swap(INCOMPLETE, RUNNING, Ordering::SeqCst); - if status == INCOMPLETE { - // We init - // We use a guard (Finish) to catch panics caused by builder - let mut finish = Finish { - state: &self.state, - panicked: true, - }; - unsafe { *self.data.get() = Some(builder()) }; - finish.panicked = false; - - status = COMPLETE; - self.state.store(status, Ordering::SeqCst); - - // This next line is strictly an optimization - return self.force_get(); + status = match self.state.compare_exchange( + INCOMPLETE, + RUNNING, + Ordering::SeqCst, + Ordering::SeqCst, + ) { + Ok(status) => { + debug_assert_eq!( + status, INCOMPLETE, + "if compare_exchange succeeded, previous status must be incomplete", + ); + // We init + // We use a guard (Finish) to catch panics caused by builder + let mut finish = Finish { + state: &self.state, + panicked: true, + }; + unsafe { *self.data.get() = Some(builder()) }; + finish.panicked = false; + + self.state.store(COMPLETE, Ordering::SeqCst); + + // This next line is strictly an optimization + return self.force_get(); + } + Err(status) => status, } } @@ -101,6 +109,8 @@ impl Once { match status { INCOMPLETE => unreachable!(), RUNNING => { + // TODO(eliza): replace with `core::hint::spin_loop` once our MSRV supports it. + #[allow(deprecated)] // We spin cpu_relax(); status = self.state.load(Ordering::SeqCst) @@ -126,7 +136,12 @@ impl Once { loop { match self.state.load(Ordering::SeqCst) { INCOMPLETE => return None, - RUNNING => cpu_relax(), // We spin + + RUNNING => { + // TODO(eliza): replace with `core::hint::spin_loop` once our MSRV supports it. + #[allow(deprecated)] + cpu_relax() // We spin + } COMPLETE => return Some(self.force_get()), PANICKED => panic!("Once has panicked"), _ => unsafe { unreachable() },