use std::time::Duration;
use tokio::{task, time::sleep};
use tractor::prelude::*;
struct Accumulator {
sum: usize,
}
enum AccumulatorMsg {
Add { a: usize },
Sub { a: usize },
}
impl Actor for Accumulator {
type Msg = AccumulatorMsg;
}
impl ActorBehavior for Accumulator {
fn handle(&mut self, msg: AccumulatorMsg, _: &Context<Self>) {
match msg {
AccumulatorMsg::Add { a } => self.sum += a,
AccumulatorMsg::Sub { a } => self.sum -= a,
}
}
}
impl ActorHooks for Accumulator {
fn stopped(&mut self) {
println!("Final sum: {}", self.sum);
}
}
#[derive(Clone)]
struct Accum(Addr<Accumulator>);
impl Accum {
fn overloaded(&self) -> bool {
self.0.len() > 1000
}
fn add(&self, a: usize) {
self.0.send(AccumulatorMsg::Add { a });
}
fn sub(&self, a: usize) {
self.0.send(AccumulatorMsg::Sub { a });
}
}
fn run() {
let actor = Accumulator { sum: 0 };
let addr = Accum(actor.start());
let _feeder = task::spawn(async move {
for _i in 0..1_000_000_usize {
while addr.overloaded() {
sleep(Duration::from_millis(1)).await;
}
addr.add(1);
}
});
}
fn main() {
ActorSystem::run_to_completion(run);
}