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;