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}