use async_trait::async_trait; use std::time::Duration; use tokio::time::sleep; use tractor::prelude::*; struct Accumulator { sum: usize, } enum AccumulatorMsg { Add { a: usize }, Sub { a: usize }, } impl Actor for Accumulator { type Msg = AccumulatorMsg; } #[async_trait] impl ActorBehaviorAsync for Accumulator { async fn handle(&mut self, msg: AccumulatorMsg, _: &Context) { match msg { AccumulatorMsg::Add { a } => self.sum += a, AccumulatorMsg::Sub { a } => self.sum -= a, } } } #[async_trait] impl ActorHooksAsync for Accumulator { async fn stopped(&mut self) { println!("Final sum: {}", self.sum); } } #[derive(Clone)] struct Accum(Addr); 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 }); } } struct Feeder; impl Actor for Feeder { type Msg = (usize, Accum); } #[async_trait] impl ActorBehaviorAsync for Feeder { async fn handle(&mut self, (num, addr): (usize, Accum), _: &Context) { for _i in 0..num { while addr.overloaded() { sleep(Duration::from_millis(1)).await; // println!("Overload"); } addr.add(1); } } } #[async_trait] impl ActorHooksAsync for Feeder {} fn run() { let accum = Accum(Accumulator { sum: 0 }.start()); let feeder = Feeder.start(); feeder.send((1_000_000, accum)); } fn main() { ActorSystem::run_to_completion(run); }