swactor/src/lib.rs

164 lines
3.8 KiB
Rust
Raw Normal View History

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<GreetMessage>,
outbox: mpsc::Sender<GreetResponse>,
state: GreeterState,
}
impl Greeter {
pub fn new(
id: GreeterId,
inbox: mpsc::Receiver<GreetMessage>,
outbox: mpsc::Sender<GreetResponse>,
) -> 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<GreeterId, mpsc::Sender<GreetMessage>>,
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<GreetMessage>) -> 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<mpsc::Sender<GreetMessage>> {
self.address_book.remove(&id)
}
pub fn get_sender(&self, id: GreeterId) -> Option<&mpsc::Sender<GreetMessage>> {
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<Greeter>,
response_rx: mpsc::Receiver<GreetResponse>,
response_tx: mpsc::Sender<GreetResponse>,
}
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<GreetResponse> {
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(())
}
}