Skip to main content

conmonrs/
channel.rs

1//! A bounded channel with any number of senders and receivers, for the stdio
2//! channels of the containers and the stdin of their attach clients.
3//!
4//! Unlike the mpsc channel of tokio, its receivers can be cloned and closed
5//! through a shared reference, and a sender can push out the oldest message
6//! of a full channel instead of waiting, see [`Sender::force_send`]. The
7//! messages stay in the order they got sent, every message goes to one of
8//! the receivers.
9
10use crate::mutex::lock;
11use std::{
12    collections::VecDeque,
13    error::Error,
14    fmt,
15    sync::{Arc, Mutex},
16};
17use tokio::sync::Notify;
18
19/// Create a channel which holds up to `capacity` messages, which must not be
20/// zero.
21pub(crate) fn bounded<T>(capacity: usize) -> (Sender<T>, Receiver<T>) {
22    assert!(capacity > 0, "channel capacity must not be zero");
23    let channel = Arc::new(Channel {
24        state: Mutex::new(State {
25            queue: VecDeque::new(),
26            closed: false,
27            senders: 1,
28            receivers: 1,
29        }),
30        capacity,
31        readable: Notify::new(),
32        writable: Notify::new(),
33        closed: Notify::new(),
34    });
35    (Sender(channel.clone()), Receiver(channel))
36}
37
38/// The state shared by the senders and receivers of a channel.
39struct Channel<T> {
40    state: Mutex<State<T>>,
41    capacity: usize,
42
43    /// Wakes the receivers once a message got queued into an empty channel,
44    /// or the channel got closed. A receiver waits only while the channel is
45    /// empty, so the other messages need no wake-up. That makes it wake all
46    /// waiters, the messages queued before they ran are for them as well.
47    readable: Notify,
48
49    /// Wakes the senders once a message got taken from a full channel, or
50    /// the channel got closed. A sender waits only while the channel is
51    /// full, all waiters get woken, see `readable`.
52    writable: Notify,
53
54    /// Wakes [`Sender::closed`] once the channel got closed, which a busy
55    /// channel would wake up for every message otherwise.
56    closed: Notify,
57}
58
59struct State<T> {
60    /// Grows on demand, an idle channel holds no buffer of its capacity.
61    queue: VecDeque<T>,
62
63    /// Set by [`Receiver::close`].
64    closed: bool,
65    senders: usize,
66    receivers: usize,
67}
68
69impl<T> State<T> {
70    /// Whether nothing can be sent anymore. The queued messages can still
71    /// be received.
72    fn is_closed(&self) -> bool {
73        self.closed || self.senders == 0 || self.receivers == 0
74    }
75}
76
77impl<T> Channel<T> {
78    /// Queue a message. A full channel fails, or drops its oldest message
79    /// with `force`.
80    fn push(&self, message: T, force: bool) -> Result<(), Push<T>> {
81        let mut state = lock(&self.state);
82        if state.is_closed() {
83            return Err(Push::Closed(message));
84        }
85        let dropped = if state.queue.len() < self.capacity {
86            None
87        } else if force {
88            state.queue.pop_front()
89        } else {
90            return Err(Push::Full(message));
91        };
92        let was_empty = state.queue.is_empty();
93        state.queue.push_back(message);
94        drop(state);
95        drop(dropped);
96        if was_empty {
97            self.readable.notify_waiters();
98        }
99        Ok(())
100    }
101
102    /// Take the oldest message.
103    fn pop(&self) -> Result<T, TryRecvError> {
104        let mut state = lock(&self.state);
105        let was_full = state.queue.len() >= self.capacity;
106        match state.queue.pop_front() {
107            Some(message) => {
108                drop(state);
109                if was_full {
110                    self.writable.notify_waiters();
111                }
112                Ok(message)
113            }
114            None if state.is_closed() => Err(TryRecvError::Closed),
115            None => Err(TryRecvError::Empty),
116        }
117    }
118
119    /// Wake everything which waits, after the channel got closed.
120    fn wake_all(&self) {
121        self.readable.notify_waiters();
122        self.writable.notify_waiters();
123        self.closed.notify_waiters();
124    }
125}
126
127/// Why a message could not be queued.
128enum Push<T> {
129    Full(T),
130    Closed(T),
131}
132
133/// The sending half of a channel.
134pub(crate) struct Sender<T>(Arc<Channel<T>>);
135
136impl<T> Sender<T> {
137    /// Send a message, waiting while the channel is full. Fails with the
138    /// message once the channel got closed or all receivers are gone.
139    pub(crate) async fn send(&self, mut message: T) -> Result<(), SendError<T>> {
140        loop {
141            // Created before the check, so that a receiver which makes room
142            // right after it wakes this one up. Only notify_waiters wakes
143            // the channel's waiters, which a Notified sees from its
144            // creation on.
145            let writable = self.0.writable.notified();
146            match self.0.push(message, false) {
147                Ok(()) => return Ok(()),
148                Err(Push::Closed(message)) => return Err(SendError(message)),
149                Err(Push::Full(full)) => message = full,
150            }
151            writable.await;
152        }
153    }
154
155    /// Send a message without waiting, a full channel drops its oldest
156    /// message for it. Fails with the message once the channel got closed or
157    /// all receivers are gone.
158    pub(crate) fn force_send(&self, message: T) -> Result<(), SendError<T>> {
159        match self.0.push(message, true) {
160            Ok(()) => Ok(()),
161            Err(Push::Closed(message) | Push::Full(message)) => Err(SendError(message)),
162        }
163    }
164
165    /// Complete once the channel got closed or all receivers are gone.
166    pub(crate) async fn closed(&self) {
167        loop {
168            // Created before the check, see Sender::send.
169            let closed = self.0.closed.notified();
170            if lock(&self.0.state).is_closed() {
171                return;
172            }
173            closed.await;
174        }
175    }
176
177    /// The number of queued messages.
178    #[cfg(test)]
179    pub(crate) fn len(&self) -> usize {
180        lock(&self.0.state).queue.len()
181    }
182}
183
184impl<T> Clone for Sender<T> {
185    fn clone(&self) -> Self {
186        lock(&self.0.state).senders += 1;
187        Self(self.0.clone())
188    }
189}
190
191impl<T> Drop for Sender<T> {
192    fn drop(&mut self) {
193        let mut state = lock(&self.0.state);
194        state.senders -= 1;
195        let last = state.senders == 0;
196        drop(state);
197        if last {
198            self.0.wake_all();
199        }
200    }
201}
202
203impl<T> fmt::Debug for Sender<T> {
204    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
205        f.debug_struct("Sender").finish_non_exhaustive()
206    }
207}
208
209/// The receiving half of a channel, whose clones share the messages.
210pub(crate) struct Receiver<T>(Arc<Channel<T>>);
211
212impl<T> Receiver<T> {
213    /// Receive the oldest message, waiting while the channel is empty. Fails
214    /// once the channel is empty and got closed or all senders are gone.
215    pub(crate) async fn recv(&self) -> Result<T, RecvError> {
216        loop {
217            // Created before the check, see Sender::send.
218            let readable = self.0.readable.notified();
219            match self.0.pop() {
220                Ok(message) => return Ok(message),
221                Err(TryRecvError::Closed) => return Err(RecvError),
222                Err(TryRecvError::Empty) => readable.await,
223            }
224        }
225    }
226
227    /// Receive the oldest message without waiting.
228    pub(crate) fn try_recv(&self) -> Result<T, TryRecvError> {
229        self.0.pop()
230    }
231
232    /// Close the channel for all senders and receivers. Sending fails from
233    /// now on, waiting senders give up, the queued messages can still be
234    /// received.
235    pub(crate) fn close(&self) {
236        lock(&self.0.state).closed = true;
237        self.0.wake_all();
238    }
239
240    /// Whether the channel got closed, or all senders are gone.
241    #[cfg(test)]
242    pub(crate) fn is_closed(&self) -> bool {
243        lock(&self.0.state).is_closed()
244    }
245
246    /// The number of senders.
247    #[cfg(test)]
248    pub(crate) fn sender_count(&self) -> usize {
249        lock(&self.0.state).senders
250    }
251}
252
253impl<T> Clone for Receiver<T> {
254    fn clone(&self) -> Self {
255        lock(&self.0.state).receivers += 1;
256        Self(self.0.clone())
257    }
258}
259
260impl<T> Drop for Receiver<T> {
261    fn drop(&mut self) {
262        let mut state = lock(&self.0.state);
263        state.receivers -= 1;
264        if state.receivers > 0 {
265            return;
266        }
267        // Nothing can receive the queued messages anymore, the senders may
268        // keep the channel around for long.
269        let queue = std::mem::take(&mut state.queue);
270        drop(state);
271        drop(queue);
272        self.0.wake_all();
273    }
274}
275
276impl<T> fmt::Debug for Receiver<T> {
277    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
278        f.debug_struct("Receiver").finish_non_exhaustive()
279    }
280}
281
282/// The channel got closed or all receivers are gone, with the message which
283/// could not be sent.
284#[derive(Debug, PartialEq, Eq)]
285pub(crate) struct SendError<T>(pub(crate) T);
286
287impl<T> fmt::Display for SendError<T> {
288    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
289        f.write_str("sending into a closed channel")
290    }
291}
292
293impl<T: fmt::Debug> Error for SendError<T> {}
294
295/// The channel is empty and got closed, or all senders are gone.
296#[derive(Clone, Copy, Debug, PartialEq, Eq)]
297pub(crate) struct RecvError;
298
299impl fmt::Display for RecvError {
300    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
301        f.write_str("receiving from an empty and closed channel")
302    }
303}
304
305impl Error for RecvError {}
306
307/// Why [`Receiver::try_recv`] got no message.
308#[derive(Clone, Copy, Debug, PartialEq, Eq)]
309pub(crate) enum TryRecvError {
310    /// The channel is empty.
311    Empty,
312
313    /// The channel is empty and got closed, or all senders are gone.
314    Closed,
315}
316
317impl fmt::Display for TryRecvError {
318    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
319        match self {
320            Self::Empty => f.write_str("receiving from an empty channel"),
321            Self::Closed => RecvError.fmt(f),
322        }
323    }
324}
325
326impl Error for TryRecvError {}
327
328#[cfg(test)]
329mod tests;