Skip to main content

radiate_core/domain/sync/
channel.rs

1use crossbeam::channel;
2
3pub struct CommandChannel<T> {
4    sender: channel::Sender<T>,
5    receiver: channel::Receiver<T>,
6}
7
8impl<T> CommandChannel<T> {
9    pub fn new() -> Self {
10        let (tx, rx) = crossbeam::channel::unbounded();
11        Self {
12            sender: tx,
13            receiver: rx,
14        }
15    }
16
17    pub fn dispatcher(&self) -> channel::Sender<T> {
18        self.sender.clone()
19    }
20
21    pub fn next(&self) -> Result<T, channel::RecvError> {
22        self.receiver.recv()
23    }
24}
25
26impl<T> Default for CommandChannel<T> {
27    fn default() -> Self {
28        Self::new()
29    }
30}
31
32impl<T> Iterator for CommandChannel<T> {
33    type Item = T;
34
35    fn next(&mut self) -> Option<Self::Item> {
36        self.receiver.recv().ok()
37    }
38}
39
40pub trait IntoPair<T> {
41    fn into_pair(self) -> (T, T);
42}
43
44impl<T> IntoPair<channel::Sender<T>> for channel::Sender<T> {
45    fn into_pair(self) -> (channel::Sender<T>, channel::Sender<T>) {
46        (self.clone(), self)
47    }
48}
49
50#[cfg(test)]
51mod tests {
52    use super::*;
53
54    #[test]
55    fn test_command_channel() {
56        let channel: CommandChannel<i32> = CommandChannel::new();
57        let dispatcher = channel.dispatcher();
58        dispatcher.send(42).unwrap();
59        assert_eq!(channel.next().unwrap(), 42);
60    }
61
62    #[test]
63    fn test_command_channel_iterator() {
64        let channel: CommandChannel<i32> = CommandChannel::new();
65        let dispatcher = channel.dispatcher();
66        dispatcher.send(1).unwrap();
67        dispatcher.send(2).unwrap();
68
69        for (i, value) in channel.into_iter().enumerate() {
70            assert_eq!(value, (i + 1) as i32);
71            if i == 1 {
72                break;
73            }
74        }
75    }
76}