Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions crossbeam-epoch/src/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,15 @@ impl Global {
/// `collect()` is not called.
#[cold]
pub(crate) fn collect(&self, guard: &Guard) {
// Advancing the epoch is only useful to make queued bags expirable, so if the queue is
// empty there is nothing to collect and the expensive `try_advance` (a `SeqCst` fence plus
// a traversal of every registered participant) is pure overhead. Skipping it only delays
// epoch advancement, never advances it early, so reclamation stays sound: any thread that
// pushed a bag will itself advance the epoch on a later `collect`.
if self.queue.is_empty(guard) {
return;
}

let global_epoch = self.try_advance(guard);

let steps = if cfg!(crossbeam_sanitize) {
Expand Down
7 changes: 7 additions & 0 deletions crossbeam-epoch/src/sync/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,13 @@ impl<T> Queue<T> {
}
}
}

/// Returns `true` if the queue is observed to be empty.
pub(crate) fn is_empty(&self, guard: &Guard) -> bool {
let head = self.head.load(Acquire, guard);
let h = unsafe { head.deref() };
h.next.load(Acquire, guard).is_null()
}
}

impl<T> Drop for Queue<T> {
Expand Down
Loading