npnc/lib.rs
1// Copyright 2017 Kyle Mayes
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Lock-free queues.
16//!
17//! # Examples
18//!
19//! ## Bounded SPSC
20//!
21//! ```
22//! extern crate npnc;
23//!
24//! use std::thread;
25//!
26//! use npnc::bounded::spsc;
27//!
28//! fn main() {
29//! let (producer, consumer) = spsc::channel(64);
30//!
31//! // Producer
32//! let b = thread::spawn(move || {
33//! for index in 0..32 {
34//! producer.produce(index).unwrap();
35//! }
36//! });
37//!
38//! // Consumer
39//! let a = thread::spawn(move || {
40//! loop {
41//! if let Ok(item) = consumer.consume() {
42//! println!("{}", item);
43//! if item == 31 {
44//! break;
45//! }
46//! }
47//! }
48//! });
49//!
50//! a.join().unwrap();
51//! b.join().unwrap();
52//! }
53//! ```
54
55#![cfg_attr(feature="valgrind", feature(alloc_system))]
56
57#![warn(missing_copy_implementations, missing_debug_implementations, missing_docs)]
58
59#[cfg(feature="valgrind")]
60extern crate alloc_system;
61
62extern crate hazard;
63
64use std::error;
65use std::fmt;
66
67#[macro_use]
68mod utility;
69mod buffer;
70pub mod bounded;
71pub mod unbounded;
72
73/// The number of pointers that fit in a 128 byte cacheline.
74#[cfg(target_pointer_width="32")]
75const POINTERS: usize = 32;
76#[cfg(target_pointer_width="64")]
77const POINTERS: usize = 16;
78
79//================================================
80// Enums
81//================================================
82
83// ConsumeError __________________________________
84
85/// Indicates the reason a `consume` operation could not return an item.
86#[derive(Copy, Clone, Debug, PartialEq, Eq)]
87pub enum ConsumeError {
88 /// The queue was empty and had no remaining producers.
89 Disconnected,
90 /// The queue was empty.
91 Empty,
92}
93
94impl error::Error for ConsumeError {
95 fn description(&self) -> &str {
96 match *self {
97 ConsumeError::Disconnected => "the queue was empty and had no remaining producers",
98 ConsumeError::Empty => "the queue was empty",
99 }
100 }
101}
102
103impl fmt::Display for ConsumeError {
104 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
105 write!(formatter, "{}", error::Error::description(self))
106 }
107}
108
109// ProduceError __________________________________
110
111/// Indicates the reason a `produce` operation rejected an item.
112#[derive(Copy, Clone, PartialEq, Eq)]
113pub enum ProduceError<T> {
114 /// The queue had no remaining consumers.
115 Disconnected(T),
116 /// The queue was full.
117 Full(T),
118}
119
120impl<T> ProduceError<T> {
121 //- Consumers --------------------------------
122
123 /// Returns the rejected item.
124 pub fn item(self) -> T {
125 match self { ProduceError::Disconnected(item) | ProduceError::Full(item) => item }
126 }
127}
128
129impl<T> error::Error for ProduceError<T> {
130 fn description(&self) -> &str {
131 match *self {
132 ProduceError::Disconnected(_) => "the queue had no remaining consumers",
133 ProduceError::Full(_) => "the queue was full",
134 }
135 }
136}
137
138impl<T> fmt::Debug for ProduceError<T> {
139 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
140 match *self {
141 ProduceError::Disconnected(_) => write!(formatter, "ProduceError::Disconnected(..)"),
142 ProduceError::Full(_) => write!(formatter, "ProduceError::Full(..)"),
143 }
144 }
145}
146
147impl<T> fmt::Display for ProduceError<T> {
148 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
149 write!(formatter, "{}", error::Error::description(self))
150 }
151}