Skip to content

Instantly share code, notes, and snippets.

@leandronsp
Created December 13, 2023 23:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save leandronsp/d39dbc99163923ab1ccdf0b9acb5974b to your computer and use it in GitHub Desktop.
Save leandronsp/d39dbc99163923ab1ccdf0b9acb5974b to your computer and use it in GitHub Desktop.
Actor model in Rust
use std::{thread, sync::{Arc, Mutex, Condvar}};
struct BlockingQueue<T> {
store: Mutex<Vec<T>>,
emitter: Condvar,
}
impl<T> BlockingQueue<T> {
fn new() -> BlockingQueue<T> {
Self {
store: Mutex::new(Vec::new()),
emitter: Condvar::new(),
}
}
fn push(&self, item: T) {
let mut store = self.store.lock().unwrap();
store.push(item);
self.emitter.notify_one();
}
fn pop(&self) -> T {
let mut store = self.store.lock().unwrap();
if store.is_empty() {
store = self.emitter.wait(store).unwrap();
}
store.remove(0)
}
}
type ActorQueue<T> = Arc<BlockingQueue<T>>;
struct Actor<T, N> {
inbox: ActorQueue<T>,
outbox: ActorQueue<N>,
}
impl<T, N> Actor<T, N>
where T: Send + 'static,
N: Send + 'static {
fn new<F, Y>(state: Y, f: F) -> Actor<T, N>
where F: Fn(Y, ActorQueue<T>, ActorQueue<N>) + Send + 'static,
Y: Send + 'static {
let inbox = Arc::new(BlockingQueue::new());
let outbox = Arc::new(BlockingQueue::new());
let thread_inbox = Arc::clone(&inbox);
let thread_outbox = Arc::clone(&outbox);
thread::spawn(move || {
f(state, thread_inbox, thread_outbox);
});
Actor { inbox, outbox, }
}
}
fn main() {
enum InboxMsg {
Deposit(i32),
Withdraw(i32),
GetBalance,
}
enum OutboxMsg {
Balance(i32),
}
let account = Actor::new(0, |mut balance, inbox, outbox| {
loop {
let msg = inbox.pop();
match msg {
InboxMsg::Deposit(amount) => balance += amount,
InboxMsg::Withdraw(amount) => balance -= amount,
InboxMsg::GetBalance => outbox.push(OutboxMsg::Balance(balance)),
}
}
});
account.inbox.push(InboxMsg::Deposit(100));
account.inbox.push(InboxMsg::Withdraw(50));
account.inbox.push(InboxMsg::GetBalance);
let OutboxMsg::Balance(balance) = account.outbox.pop();
println!("Balance: {:?}", balance);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment