lf_queue/
lib.rs

1#![deny(
2    warnings,
3    rustdoc::broken_intra_doc_links,
4    rustdoc::private_intra_doc_links,
5    missing_docs,
6    missing_debug_implementations,
7    trivial_casts,
8    trivial_numeric_casts,
9    unreachable_pub,
10    unsafe_op_in_unsafe_fn,
11    unused_crate_dependencies,
12    unused_extern_crates,
13    unused_import_braces,
14    unused_lifetimes,
15    unused_qualifications,
16    unused_results,
17    rust_2018_idioms
18)]
19
20//! A lock-free multi-producer multi-consumer unbounded queue.
21//!
22//! # Examples
23//!
24//! Single Producer - Single Consumer:
25//!
26//! ```
27//! use lf_queue::Queue;
28//!
29//! const COUNT: usize = 1_000;
30//! let queue: Queue<usize> = Queue::new();
31//!
32//! for i in 0..COUNT {
33//!     queue.push(i);
34//! }
35//!
36//! for i in 0..COUNT {
37//!     assert_eq!(i, queue.pop().unwrap());
38//! }
39//!
40//! assert!(queue.pop().is_none());
41//! ```
42//! Multi Producer - Single Consumer:
43//!
44//! ```
45//! use lf_queue::Queue;
46//! use std::thread;
47//!
48//! const COUNT: usize = 1_000;
49//! const CONCURRENCY: usize = 4;
50//!
51//! let queue: Queue<usize> = Queue::new();
52//!
53//! let ths: Vec<_> = (0..CONCURRENCY)
54//!     .map(|_| {
55//!         let q = queue.clone();
56//!         thread::spawn(move || {
57//!             for i in 0..COUNT {
58//!                 q.push(i);
59//!             }
60//!         })
61//!     })
62//!     .collect();
63//!
64//! for th in ths {
65//!     th.join().unwrap();
66//! }
67//!
68//! for _ in 0..COUNT * CONCURRENCY {
69//!     assert!(queue.pop().is_some());
70//! }
71//!
72//! assert!(queue.pop().is_none());
73//! ```
74//!
75//! Single Producer - Multi Consumer:
76//!
77//! ```
78//! use lf_queue::Queue;
79//! use std::thread;
80//!
81//! const COUNT: usize = 1_000;
82//! const CONCURRENCY: usize = 4;
83//!
84//! let queue: Queue<usize> = Queue::new();
85//!
86//! for i in 0..COUNT * CONCURRENCY {
87//!     queue.push(i);
88//! }
89//!
90//! let ths: Vec<_> = (0..CONCURRENCY)
91//!     .map(|_| {
92//!         let q = queue.clone();
93//!         thread::spawn(move || {
94//!             for _ in 0..COUNT {
95//!                 loop {
96//!                     if q.pop().is_some() {
97//!                         break;
98//!                     }
99//!                 }
100//!             }
101//!         })
102//!     })
103//!     .collect();
104//!
105//! for th in ths {
106//!     th.join().unwrap();
107//! }
108//!
109//! assert!(queue.pop().is_none());
110//! ```
111//!
112//! Multi Producer - Multi Consumer:
113//!
114//! ```
115//! use lf_queue::Queue;
116//! use std::sync::atomic::{AtomicUsize, Ordering};
117//! use std::sync::Arc;
118//! use std::thread;
119//!
120//! const COUNT: usize = 1_000;
121//! const CONCURRENCY: usize = 4;
122//!
123//! let queue: Queue<usize> = Queue::new();
124//! let items = Arc::new((0..COUNT).map(|_| AtomicUsize::new(0)).collect::<Vec<_>>());
125//!
126//! let ths: Vec<_> = (0..CONCURRENCY)
127//!     .map(|_| {
128//!         let q = queue.clone();
129//!         let its = items.clone();
130//!         thread::spawn(move || {
131//!             for _ in 0..COUNT {
132//!                 let n = loop {
133//!                     if let Some(x) = q.pop() {
134//!                         break x;
135//!                     } else {
136//!                         thread::yield_now();
137//!                     }
138//!                 };
139//!                 its[n].fetch_add(1, Ordering::SeqCst);
140//!             }
141//!         })
142//!     })
143//!     .map(|_| {
144//!         let q = queue.clone();
145//!         thread::spawn(move || {
146//!             for i in 0..COUNT {
147//!                 q.push(i);
148//!             }
149//!         })
150//!     })
151//!     .collect();
152//!
153//! for th in ths {
154//!     th.join().unwrap();
155//! }
156//!
157//! thread::sleep(std::time::Duration::from_millis(10));
158//!
159//! for c in &*items {
160//!     assert_eq!(c.load(Ordering::SeqCst), CONCURRENCY);
161//! }
162//!
163//! assert!(queue.pop().is_none());
164//! ```
165
166mod queue;
167
168pub(crate) mod cache_pad;
169pub(crate) mod node;
170pub(crate) mod slot;
171pub(crate) mod variant;
172
173pub use queue::Queue;