pub struct BackoffState<S> { /* private fields */ }Expand description
A wrapper around a BackoffStrategy to be used in CAS loops when the atomic value must be
checked after each reload.
Contrary to BackoffStrategy::backoff_reload, it allows checking for a termination condition
and early exiting the loop before performing the backoff.
In order to avoid code duplication with the checks after the reloads,
BackoffState::backoff_reload should be called at every iteration of the CAS loop before the
CAS. However, to avoid performing a backoff before any CAS failure, BackoffState is
initialized as disabled, and enabled after the first backoff_reload call.
§Examples
fn try_update_with_backoff(
atomic: &AtomicUsize,
set_order: Ordering,
fetch_order: Ordering,
mut f: impl FnMut(usize) -> Option<usize>,
strategy: impl BackoffStrategy,
) -> Result<usize, usize> {
let mut backoff = BackoffState::new(strategy);
let mut current = atomic.load(fetch_order);
loop {
// Check the termination condition before backing off.
let new = f(current).ok_or(current)?;
// If the value has been reloaded, `new` must be recomputed.
if backoff.backoff_reload(&mut current, || atomic.load(fetch_order)) {
continue;
}
match atomic.compare_exchange_weak(current, new, set_order, fetch_order) {
Ok(x) => return Ok(x),
Err(cur) => current = cur,
}
}
}Implementations§
Source§impl<S: BackoffStrategy> BackoffState<S>
impl<S: BackoffStrategy> BackoffState<S>
Sourcepub fn new(strategy: S) -> Self
pub fn new(strategy: S) -> Self
Creates a new BackoffState with the given backoff strategy.
The backoff starts as disabled so the first iteration before any CAS failure doesn’t wait.
Sourcepub fn enable(self) -> Self
pub fn enable(self) -> Self
Starts the backoff in enabled mode.
It is useful when the first CAS iteration is inlined in a hot function, and the complete CAS loop with the backoff is outlined in a cold function, so the backoff must start enabled after a CAS failure.
Sourcepub fn backoff_reload<T: PartialEq, F: FnOnce() -> T>(
&mut self,
current: &mut T,
reload: F,
) -> bool
pub fn backoff_reload<T: PartialEq, F: FnOnce() -> T>( &mut self, current: &mut T, reload: F, ) -> bool
Enables the backoff for the next iteration or perform a backoff if already enabled.
Returns true if the current atomic value has been updated after a reload, in which case
the new atomic value should be recomputed before retrying the CAS.
The backoff can be temporarily disabled after a reload triggered by
RetryStrategy::Reload in order to execute the CAS with the reloaded value at the next
iteration.