Skip to main content

logicaffeine_runtime/
channel.rs

1//! Channels — FIFO, bounded, move-semantics pipes (the language's `Pipe`).
2//!
3//! A channel carries [`RtPayload`] values in FIFO order. Capacity `Some(n)` bounds
4//! the buffer (a full channel blocks senders); `Some(0)` is a rendezvous channel
5//! (every send hands off directly to a receiver); `None` is unbounded.
6
7use std::collections::VecDeque;
8
9use crate::payload::RtPayload;
10use crate::task::TaskId;
11
12/// A scheduler-assigned channel handle.
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
14pub struct ChanId(pub u64);
15
16/// A channel's buffer and its blocked senders/receivers.
17pub(crate) struct Chan {
18    /// `Some(n)` bounded (n may be 0 = rendezvous); `None` unbounded.
19    pub capacity: Option<usize>,
20    /// Buffered values awaiting a receiver, FIFO.
21    pub queue: VecDeque<RtPayload>,
22    /// Senders parked because the buffer was full, with the value they want to send.
23    pub blocked_senders: VecDeque<(TaskId, RtPayload)>,
24    /// Receivers parked because the buffer was empty (includes select-waiters).
25    pub blocked_receivers: VecDeque<TaskId>,
26    /// Once closed, a receive on an empty channel yields `Nothing` instead of
27    /// blocking, and a closed channel counts as receive-ready for `Select`.
28    pub closed: bool,
29}
30
31impl Chan {
32    pub(crate) fn new(capacity: Option<usize>) -> Self {
33        Chan {
34            capacity,
35            queue: VecDeque::new(),
36            blocked_senders: VecDeque::new(),
37            blocked_receivers: VecDeque::new(),
38            closed: false,
39        }
40    }
41
42    /// Is there buffer room for one more value right now?
43    pub(crate) fn has_room(&self) -> bool {
44        match self.capacity {
45            None => true,
46            Some(cap) => self.queue.len() < cap,
47        }
48    }
49
50    /// Can a receive succeed immediately (a buffered value, a waiting sender, or
51    /// a closed channel — which delivers `Nothing`)?
52    pub(crate) fn can_recv(&self) -> bool {
53        !self.queue.is_empty() || !self.blocked_senders.is_empty() || self.closed
54    }
55}