use crate::dispatch::lookup::ActorLookup;
use arc_swap::ArcSwap;
use std::sync::Arc;
mod defaults {
use super::FeedbackAlgorithm;
pub const INITIAL_INTERVAL_MS: u64 = 500;
pub const MIN_INTERVAL_MS: u64 = 20;
pub const MAX_INTERVAL_MS: u64 = 5_000;
pub const ADDITIVE_INCREASE: u64 = 500;
pub const MULTIPLICATIVE_DECREASE_DEN: u64 = 2;
pub const ALGORITHM: FeedbackAlgorithm = super::FeedbackAlgorithm::AIMD;
}
pub struct ActorRefReaper {
scheduled: bool,
strategy: UpdateStrategy,
}
pub struct UpdateStrategy {
curr: u64,
incr: u64,
decr: u64,
min: u64,
max: u64,
algo: FeedbackAlgorithm,
}
pub enum FeedbackAlgorithm {
AIMD, MIMD, }
impl Default for ActorRefReaper {
fn default() -> Self {
ActorRefReaper {
scheduled: false,
strategy: UpdateStrategy::new(
defaults::INITIAL_INTERVAL_MS,
defaults::MIN_INTERVAL_MS,
defaults::MAX_INTERVAL_MS,
defaults::ADDITIVE_INCREASE,
defaults::MULTIPLICATIVE_DECREASE_DEN,
defaults::ALGORITHM,
),
}
}
}
impl ActorRefReaper {
pub fn new(
initial_interval: u64,
min: u64,
max: u64,
incr: u64,
decr: u64,
algo: FeedbackAlgorithm,
) -> Self {
ActorRefReaper {
scheduled: false,
strategy: UpdateStrategy::new(initial_interval, min, max, incr, decr, algo),
}
}
pub fn run<T: ActorLookup>(&self, table: &ArcSwap<T>) -> usize {
let mut removed = 0;
table.rcu(|current| {
let mut next = (*current).clone();
removed = next.cleanup();
Arc::new(next)
});
removed
}
pub fn strategy(&self) -> &UpdateStrategy {
&self.strategy
}
pub fn strategy_mut(&mut self) -> &mut UpdateStrategy {
&mut self.strategy
}
pub fn schedule(&mut self) {
self.scheduled = true;
}
pub fn is_scheduled(&self) -> bool {
self.scheduled
}
}
impl UpdateStrategy {
pub fn new(
curr: u64,
min: u64,
max: u64,
incr: u64,
decr: u64,
algo: FeedbackAlgorithm,
) -> Self {
UpdateStrategy {
curr,
incr,
decr,
min,
max,
algo,
}
}
pub fn curr(&self) -> u64 {
self.curr
}
pub fn incr(&mut self) -> u64 {
use self::FeedbackAlgorithm::*;
self.curr = match self.algo {
AIMD => self.curr + self.incr,
MIMD => self.curr * self.incr,
}
.min(self.max);
self.curr
}
pub fn decr(&mut self) -> u64 {
use self::FeedbackAlgorithm::*;
self.curr = match self.algo {
AIMD | MIMD => self.curr / self.decr,
}
.max(self.min);
self.curr
}
}