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
106
107
//! Magnetic contains a set of high-performance queues useful for developing
//! low-latency applications. All queues are FIFO unless otherwise specified.
//!
//! # Examples
//!
//! ```
//! use std::thread::spawn;
//! use magnetic::spsc::spsc_queue;
//! use magnetic::buffer::dynamic::DynamicBuffer;
//! use magnetic::{Producer, Consumer};
//!
//! let (p, c) = spsc_queue(DynamicBuffer::new(32).unwrap());
//!
//! // Push and pop within a single thread
//! p.push(1).unwrap();
//! assert_eq!(c.pop(), Ok(1));
//!
//! // Push and pop from multiple threads. Since this example is using the
//! // SPSC queue, only one producer and one consumer are allowed.
//! let t1 = spawn(move || {
//!     for i in 0..10 {
//!         println!("Producing {}", i);
//!         p.push(i).unwrap();
//!     }
//!     p
//! });
//!
//! let t2 = spawn(move || {
//!     loop {
//!         let i = c.pop().unwrap();
//!         println!("Consumed {}", i);
//!         if i == 9 { break; }
//!     }
//! });
//!
//! t1.join().unwrap();
//! t2.join().unwrap();
//! ```

#![deny(missing_docs)]

pub mod buffer;
pub mod mpmc;
pub mod mpsc;
pub mod spmc;
pub mod spsc;
mod util;

/// Possible errors for `Producer::push`
#[derive(Debug, PartialEq)]
pub enum PushError<T> {
    /// Consumer was destroyed
    Disconnected(T),
}

/// Possible errors for `Producer::try_push`
#[derive(Debug, PartialEq)]
pub enum TryPushError<T> {
    /// Queue was full
    Full(T),
    /// Consumer was destroyed
    Disconnected(T),
}

/// Possible errors for `Consumer::pop`
#[derive(Debug, PartialEq)]
pub enum PopError {
    /// Producer was destroyed
    Disconnected,
}

/// Possible errors for `Consumer::try_pop`
#[derive(Debug, PartialEq)]
pub enum TryPopError {
    /// Queue was empty
    Empty,
    /// Producer was destroyed
    Disconnected,
}

/// The consumer end of the queue allows for sending data. `Producer<T>` is
/// always `Send`, but is only `Sync` for multi-producer (MPSC, MPMC) queues.
pub trait Producer<T> {
    /// Add value to front of the queue. This method will block if the queue
    /// is currently full.
    fn push(&self, value: T) -> Result<(), PushError<T>>;

    /// Attempt to add a value to the front of the queue. If the value was
    /// added successfully, `None` will be returned. If unsuccessful, `value`
    /// will be returned. An unsuccessful push indicates that the queue was
    /// full.
    fn try_push(&self, value: T) -> Result<(), TryPushError<T>>;
}

/// The consumer end of the queue allows for receiving data. `Consumer<T>` is
/// always `Send`, but is only `Sync` for multi-consumer (SPMC, MPMC) queues.
pub trait Consumer<T> {
    /// Remove value from the end of the queue. This method will block if the
    /// queue is currently empty.
    fn pop(&self) -> Result<T, PopError>;

    /// Attempt to remove a value from the end of the queue. If the value was
    /// removed successfully, `Some(T)` will be returned. If unsuccessful,
    /// `None` will be returned. An unsuccessful pop indicates that the queue
    /// was empty.
    fn try_pop(&self) -> Result<T, TryPopError>;
}