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<Self>) {
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<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 });
}
}
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<Self>) {
for _i in 0..num {
while addr.overloaded() {
sleep(Duration::from_millis(1)).await;
}
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);
}