1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
//! A no-std Single Producer, Single Consumer channel for unidirectional message exchange between
//! modules. This module don't use anything from the standard lib and can be easily used in no-std
//! enviroments. We only use mem::take from [core].

use core::mem::take;

use crate::prelude::Vec;

/// A (Send + Sync) single producer, single consumer channel to notify modules about things.
/// The api is super minimalistic to reduce external dependecies, including from the std-lib
///
/// One notable difference from the standard mspc channel is that this channel's ends are't
/// two different types, while this is possible, there's no reason to do that. Specially
/// considering that to get a good compile-time asurance that both ends will not be shared, the
/// channel must not be [Send], but this is one of the main requirements to use this channel in
/// async code. Moreover, if two worker threads are meant to be identical threads balancing their
/// work, it might be beneficial to use this same channel as a de-facto single producer, multiple
/// consumer channel for work distribution.
/// # Example
/// ```
/// use floresta_common::spsc;
/// let channel = spsc::Channel::new();
///
/// // Send something
/// channel.send(1);
/// // Read the same thing back
/// assert_eq!(channel.recv().next(), Some(1));
/// ```
#[derive(Debug, Default)]
pub struct Channel<T> {
    /// The data pending for read
    content: spin::Mutex<Vec<T>>,
}

impl<T> Channel<T> {
    /// Creates a new channel
    ///
    /// # Example
    /// ```
    /// use floresta_common::spsc;
    /// let channel = spsc::Channel::new();
    ///
    /// channel.send(1);
    /// assert_eq!(channel.recv().next(), Some(1));
    /// ```
    pub fn new() -> Self {
        Channel {
            content: spin::Mutex::new(Vec::new()),
        }
    }
    /// Sends some data through a channel
    ///
    /// # Example
    /// ```
    /// use floresta_common::spsc;
    /// let channel = spsc::Channel::new();
    ///
    /// channel.send(1);
    /// assert_eq!(channel.recv().next(), Some(1));
    /// ```
    pub fn send(&self, data: T) {
        self.content.lock().push(data);
    }
    /// Reads from a channel
    ///
    /// This method returns an iterator over all alements inside a [Channel]
    pub fn recv(&self) -> RecvIter<T> {
        let inner = take(&mut *self.content.lock());
        RecvIter { inner }
    }
}

/// An iterator issued every time someone calls `recv`.
///
/// This iterator takes all itens available for reading in a channel
/// and lets the consumer iterate over them, without acquiring the lock
/// every time (the mutex is only locked when `recv` is called).
///
/// # Example
/// ```
/// use floresta_common::spsc;
/// let channel = spsc::Channel::new();
///
/// channel.send(0);
/// channel.send(1);
///
/// for (i, el) in channel.recv().enumerate() {
///     assert_eq!(i, el);
/// }
/// // A second read should create an empty iterator
/// assert_eq!(channel.recv().next(), None);
/// ```
pub struct RecvIter<T> {
    inner: Vec<T>,
}

impl<T> Iterator for RecvIter<T> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        if self.inner.is_empty() {
            return None;
        }
        Some(self.inner.remove(0))
    }
}