#[allow(missing_docs)]
mod future;
mod layer;
mod service;
use std::time::Duration;
pub use self::{
future::ResponseFuture,
layer::{DelayLayer, DelayLayerWith, JitterDelayLayer, JitterDelayLayerWith},
service::{Delay, DelayWith, JitterDelay, JitterDelayWith},
};
fn jittered_duration(base: Duration, pct: f64) -> Duration {
let jitter = base.mul_f64(pct);
let low = base.saturating_sub(jitter);
let high = base.saturating_add(jitter);
if low >= high {
return base;
}
let rand = fast_random();
let frac = (rand as f64) / (u64::MAX as f64);
let span = (high - low).as_secs_f64();
low + Duration::from_secs_f64(span * frac)
}
fn fast_random() -> u64 {
use std::{
cell::Cell,
collections::hash_map::RandomState,
hash::{BuildHasher, Hasher},
num::Wrapping,
};
thread_local! {
static RNG: Cell<Wrapping<u64>> = Cell::new(Wrapping(seed()));
}
#[inline]
fn seed() -> u64 {
let seed = RandomState::new();
let mut out = 0;
let mut cnt = 0;
while out == 0 {
cnt += 1;
let mut hasher = seed.build_hasher();
hasher.write_usize(cnt);
out = hasher.finish();
}
out
}
RNG.with(|rng| {
let mut n = rng.get();
debug_assert_ne!(n.0, 0);
n ^= n >> 12;
n ^= n << 25;
n ^= n >> 27;
rng.set(n);
n.0.wrapping_mul(0x2545_f491_4f6c_dd1d)
})
}