Closed
Description
I believe that (comments removed)
pub fn call_once<F>(&'static self, f: F) where F: FnOnce() {
if self.cnt.load(Ordering::Acquire) < 0 {
return
}
let prev = self.cnt.fetch_add(1, Ordering::Acquire);
if prev < 0 {
self.cnt.store(isize::MIN, Ordering::Release);
return
}
let guard = self.mutex.lock();
if self.cnt.load(Ordering::Relaxed) > 0 {
f();
let prev = self.cnt.swap(isize::MIN, Ordering::Release);
self.lock_cnt.store(prev, Ordering::Release);
}
drop(guard);
if self.lock_cnt.fetch_add(-1, Ordering::AcqRel) == 1 {
unsafe { self.mutex.destroy() }
}
}
is the correct set of barriers (I'm not certain if the lock_cnt barriers can be Relaxed instead, but it's pretty irrelevant and these are safe).
At the very least I am /certain/ that the very first load can be Acquire instead of SeqCst, which removes the barrier from the fast-path on x86.