pub trait BackoffStrategy:
Default
+ Send
+ Sync
+ 'static {
const BACKOFF: bool = true;
// Required method
fn backoff(&mut self) -> RetryStrategy;
// Provided methods
fn will_reload(&self) -> bool { ... }
fn backoff_reload<T: PartialEq, F: FnMut() -> T>(
&mut self,
current: T,
reload: F,
) -> T { ... }
fn backoff_until<C: BackoffUntilCondition, F: FnMut() -> C>(
&mut self,
f: F,
) -> C::Result { ... }
}Expand description
Backoff strategy to be used after an atomic compare-and-swap (CAS) failure and in spin loops.
Waiting before retrying a failed CAS can greatly reduce the contention on the atomic’s cache line, and improve the performance of CAS loops.
Spin loops also benefit from backoff as it avoids keeping the CPU 100% busy while waiting, at little latency cost.
Provided Associated Constants§
Sourceconst BACKOFF: bool = true
const BACKOFF: bool = true
Whether the strategy does backoff or not.
Some algorithms may have a different behavior depending on whether backoff is used; for example switching between an unbounded spin loop or a thread parking algorithm. This constant can be used for this purpose.
It should be set to false only for NoBackoff.
Required Methods§
Sourcefn backoff(&mut self) -> RetryStrategy
fn backoff(&mut self) -> RetryStrategy
Performs backoff and returns how the CAS should be retried.
will_reload should also be implemented accordingly.
In spin loops, the returned value can simply be ignored.
Provided Methods§
Sourcefn will_reload(&self) -> bool
fn will_reload(&self) -> bool
Returns true if the next call to backoff will not return
RetryStrategy::NoReload.
This hint can be used to downgrade the failure ordering of the CAS to Relaxed when the
returned value is overwritten anyway.
Sourcefn backoff_reload<T: PartialEq, F: FnMut() -> T>(
&mut self,
current: T,
reload: F,
) -> T
fn backoff_reload<T: PartialEq, F: FnMut() -> T>( &mut self, current: T, reload: F, ) -> T
Performs backoff after a failed CAS and reloads the atomic value according to the returned
RetryStrategy.
ReloadUntilUnchanged causes this function to loop until the value stops changing. If the
value returned by the failed CAS must be tested between reloads, use BackoffState
instead.
§Example
fn update_with_backoff(
atomic: &AtomicUsize,
set_order: Ordering,
fetch_order: Ordering,
mut f: impl FnMut(usize) -> usize,
mut strategy: impl BackoffStrategy,
) -> usize {
let mut current = atomic.load(fetch_order);
loop {
let failure_order = if strategy.will_reload() {
Ordering::Relaxed
} else {
fetch_order
};
match atomic.compare_exchange_weak(current, f(current), set_order, failure_order) {
Ok(x) => return x,
Err(cur) => current = strategy.backoff_reload(cur, || atomic.load(fetch_order)),
}
}
}Sourcefn backoff_until<C: BackoffUntilCondition, F: FnMut() -> C>(
&mut self,
f: F,
) -> C::Result
fn backoff_until<C: BackoffUntilCondition, F: FnMut() -> C>( &mut self, f: F, ) -> C::Result
Loops until a condition is fulfilled, performing backoff at each iteration.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".