pub mod error; use std::{ marker::PhantomData, sync::{Mutex, mpsc::TryRecvError}, }; use crate::error::{Error, Result, convert_err}; use std::sync::mpsc; use bytemuck::{Pod, Zeroable}; #[repr(C)] #[derive(Copy, Clone, Pod, Zeroable)] struct GreeterState { pub num_greeted: usize, } enum GreetMessage { Name(String), } enum GreetResponse { Greeting(String), } type GreeterId = u64; struct Greeter { id: GreeterId, inbox: mpsc::Receiver, outbox: mpsc::Sender, state: GreeterState, } impl Greeter { pub fn new( id: GreeterId, inbox: mpsc::Receiver, outbox: mpsc::Sender, ) -> Self { Self { id, inbox, outbox, state: GreeterState { num_greeted: 0 }, } } pub fn id(&self) -> GreeterId { self.id } pub fn process_message(&mut self) -> Result<()> { match self.inbox.try_recv() { Ok(m) => { let GreetMessage::Name(n) = m; self.outbox .send(GreetResponse::Greeting(format!("Hello, {n}!"))) .map_err(convert_err)?; self.state.num_greeted += 1; } Err(e) => match e { TryRecvError::Empty => return Ok(()), TryRecvError::Disconnected => { return Err("Outbox has been disconnected, actor in an improper state".into()); } }, } Ok(()) } } use std::collections::HashMap; struct Router { address_book: HashMap>, next_id: GreeterId, } impl Router { pub fn new() -> Self { Self { address_book: HashMap::new(), next_id: 0, } } pub fn register(&mut self, sender: mpsc::Sender) -> GreeterId { let id = self.next_id; self.next_id += 1; self.address_book.insert(id, sender); id } pub fn unregister(&mut self, id: GreeterId) -> Option> { self.address_book.remove(&id) } pub fn get_sender(&self, id: GreeterId) -> Option<&mpsc::Sender> { self.address_book.get(&id) } pub fn send(&self, id: GreeterId, message: GreetMessage) -> Result<()> { match self.address_book.get(&id) { Some(sender) => sender.send(message).map_err(convert_err), None => Err(format!("No sender found for id {}", id).into()), } } } struct Runtime { router: Router, greeters: Vec, response_rx: mpsc::Receiver, response_tx: mpsc::Sender, } impl Runtime { pub fn new() -> Self { let (response_tx, response_rx) = mpsc::channel(); Self { router: Router::new(), greeters: Vec::new(), response_rx, response_tx, } } pub fn spawn_greeter(&mut self) -> GreeterId { let (inbox_tx, inbox_rx) = mpsc::channel(); let id = self.router.register(inbox_tx); let greeter = Greeter::new(id, inbox_rx, self.response_tx.clone()); self.greeters.push(greeter); id } pub fn send_message(&self, id: GreeterId, message: GreetMessage) -> Result<()> { self.router.send(id, message) } pub fn tick(&mut self) -> Result<()> { for greeter in &mut self.greeters { greeter.process_message()?; } Ok(()) } pub fn try_recv_response(&self) -> Option { self.response_rx.try_recv().ok() } pub fn run_until_idle(&mut self) -> Result<()> { loop { self.tick()?; if self.response_rx.try_recv().is_err() { break; } } Ok(()) } }