-
Notifications
You must be signed in to change notification settings - Fork 13.7k
Closed
Labels
C-enhancementCategory: An issue proposing an enhancement or a PR with one.Category: An issue proposing an enhancement or a PR with one.I-slowIssue: Problems and improvements with respect to performance of generated code.Issue: Problems and improvements with respect to performance of generated code.T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.Relevant to the library API team, which will review and decide on the PR/issue.
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.
Metadata
Metadata
Assignees
Labels
C-enhancementCategory: An issue proposing an enhancement or a PR with one.Category: An issue proposing an enhancement or a PR with one.I-slowIssue: Problems and improvements with respect to performance of generated code.Issue: Problems and improvements with respect to performance of generated code.T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.Relevant to the library API team, which will review and decide on the PR/issue.