compio-actor 0.1.0

Actors for Compio
Documentation
use std::{
    num::NonZeroUsize,
    sync::{Arc, atomic::AtomicBool},
};

use flume::Receiver as FlumeReceiver;
use futures_util::{FutureExt, pin_mut, select_biased};

use super::{Mailbox, MailboxInner, Name};
use crate::{Actor, actor::Delivering};

pub(crate) struct Receiver<A: Actor> {
    messages: FlumeReceiver<Delivering<A>>,
    stop: FlumeReceiver<()>,
}

impl<A: Actor> Receiver<A> {
    pub(crate) async fn recv(&self) -> MailboxEvent<A> {
        let stop = self.stop.recv_async().fuse();
        let message = self.messages.recv_async().fuse();
        pin_mut!(stop, message);

        select_biased! {
            _ = stop => MailboxEvent::Stop,
            message = message => match message {
                Ok(message) => MailboxEvent::Message(message),
                Err(_) => MailboxEvent::Stop,
            },
        }
    }
}

pub(crate) enum MailboxEvent<A: Actor> {
    Message(Delivering<A>),
    Stop,
}

pub(crate) fn make_mailbox<A: Actor>(
    name: Option<Name>,
    capacity: NonZeroUsize,
) -> (Mailbox<A>, Receiver<A>) {
    let (message_tx, message_rx) = flume::bounded(capacity.get());
    let (stop_tx, stop_rx) = flume::bounded(1);
    let inner = Arc::new(MailboxInner {
        name,
        messages: message_tx,
        stop: stop_tx,
        stopping: AtomicBool::new(false),
        capacity,
    });

    (
        Mailbox { inner },
        Receiver {
            messages: message_rx,
            stop: stop_rx,
        },
    )
}