Skip to content

Commit

Permalink
Remove PopError
Browse files Browse the repository at this point in the history
This changes `pop` methods to return `Option`.
  • Loading branch information
taiki-e committed Aug 30, 2020
1 parent 35515d9 commit 69766ea
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 60 deletions.
6 changes: 3 additions & 3 deletions crossbeam-channel/benchmarks/segqueue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ fn spsc() {

for _ in 0..MESSAGES {
loop {
if q.pop().is_err() {
if q.pop().is_none() {
thread::yield_now();
} else {
break;
Expand All @@ -55,7 +55,7 @@ fn mpsc() {

for _ in 0..MESSAGES {
loop {
if q.pop().is_err() {
if q.pop().is_none() {
thread::yield_now();
} else {
break;
Expand All @@ -82,7 +82,7 @@ fn mpmc() {
scope.spawn(|_| {
for _ in 0..MESSAGES / THREADS {
loop {
if q.pop().is_err() {
if q.pop().is_none() {
thread::yield_now();
} else {
break;
Expand Down
18 changes: 9 additions & 9 deletions crossbeam-queue/src/array_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use core::sync::atomic::{self, AtomicUsize, Ordering};

use crossbeam_utils::{Backoff, CachePadded};

use crate::err::{PopError, PushError};
use crate::err::PushError;

/// A slot in a queue.
struct Slot<T> {
Expand Down Expand Up @@ -50,7 +50,7 @@ struct Slot<T> {
/// assert_eq!(q.push('a'), Ok(()));
/// assert_eq!(q.push('b'), Ok(()));
/// assert_eq!(q.push('c'), Err(PushError('c')));
/// assert_eq!(q.pop(), Ok('a'));
/// assert_eq!(q.pop(), Some('a'));
/// ```
pub struct ArrayQueue<T> {
/// The head of the queue.
Expand Down Expand Up @@ -218,20 +218,20 @@ impl<T> ArrayQueue<T> {

/// Attempts to pop an element from the queue.
///
/// If the queue is empty, an error is returned.
/// If the queue is empty, `None` is returned.
///
/// # Examples
///
/// ```
/// use crossbeam_queue::{ArrayQueue, PopError};
/// use crossbeam_queue::ArrayQueue;
///
/// let q = ArrayQueue::new(1);
/// assert_eq!(q.push(10), Ok(()));
///
/// assert_eq!(q.pop(), Ok(10));
/// assert_eq!(q.pop(), Err(PopError));
/// assert_eq!(q.pop(), Some(10));
/// assert!(q.pop().is_none());
/// ```
pub fn pop(&self) -> Result<T, PopError> {
pub fn pop(&self) -> Option<T> {
let backoff = Backoff::new();
let mut head = self.head.load(Ordering::Relaxed);

Expand Down Expand Up @@ -268,7 +268,7 @@ impl<T> ArrayQueue<T> {
let msg = unsafe { slot.value.get().read().assume_init() };
slot.stamp
.store(head.wrapping_add(self.one_lap), Ordering::Release);
return Ok(msg);
return Some(msg);
}
Err(h) => {
head = h;
Expand All @@ -281,7 +281,7 @@ impl<T> ArrayQueue<T> {

// If the tail equals the head, that means the channel is empty.
if tail == head {
return Err(PopError);
return None;
}

backoff.spin();
Expand Down
19 changes: 0 additions & 19 deletions crossbeam-queue/src/err.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,5 @@
use core::fmt;

/// Error which occurs when popping from an empty queue.
#[derive(Clone, Copy, Eq, PartialEq)]
pub struct PopError;

impl fmt::Debug for PopError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
"PopError".fmt(f)
}
}

impl fmt::Display for PopError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
"popping from an empty queue".fmt(f)
}
}

#[cfg(feature = "std")]
impl ::std::error::Error for PopError {}

/// Error which occurs when pushing into a full queue.
#[derive(Clone, Copy, Eq, PartialEq)]
pub struct PushError<T>(pub T);
Expand Down
2 changes: 1 addition & 1 deletion crossbeam-queue/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ cfg_if::cfg_if! {
mod seg_queue;

pub use self::array_queue::ArrayQueue;
pub use self::err::{PopError, PushError};
pub use self::err::PushError;
pub use self::seg_queue::SegQueue;
}
}
24 changes: 11 additions & 13 deletions crossbeam-queue/src/seg_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ use core::sync::atomic::{self, AtomicPtr, AtomicUsize, Ordering};

use crossbeam_utils::{Backoff, CachePadded};

use crate::err::PopError;

// Bits indicating the state of a slot:
// * If a value has been written into the slot, `WRITE` is set.
// * If a value has been read from the slot, `READ` is set.
Expand Down Expand Up @@ -123,16 +121,16 @@ struct Position<T> {
/// # Examples
///
/// ```
/// use crossbeam_queue::{PopError, SegQueue};
/// use crossbeam_queue::SegQueue;
///
/// let q = SegQueue::new();
///
/// q.push('a');
/// q.push('b');
///
/// assert_eq!(q.pop(), Ok('a'));
/// assert_eq!(q.pop(), Ok('b'));
/// assert_eq!(q.pop(), Err(PopError));
/// assert_eq!(q.pop(), Some('a'));
/// assert_eq!(q.pop(), Some('b'));
/// assert!(q.pop().is_none());
/// ```
pub struct SegQueue<T> {
/// The head of the queue.
Expand Down Expand Up @@ -266,20 +264,20 @@ impl<T> SegQueue<T> {

/// Pops an element from the queue.
///
/// If the queue is empty, an error is returned.
/// If the queue is empty, `None` is returned.
///
/// # Examples
///
/// ```
/// use crossbeam_queue::{PopError, SegQueue};
/// use crossbeam_queue::SegQueue;
///
/// let q = SegQueue::new();
///
/// q.push(10);
/// assert_eq!(q.pop(), Ok(10));
/// assert_eq!(q.pop(), Err(PopError));
/// assert_eq!(q.pop(), Some(10));
/// assert!(q.pop().is_none());
/// ```
pub fn pop(&self) -> Result<T, PopError> {
pub fn pop(&self) -> Option<T> {
let backoff = Backoff::new();
let mut head = self.head.index.load(Ordering::Acquire);
let mut block = self.head.block.load(Ordering::Acquire);
Expand All @@ -304,7 +302,7 @@ impl<T> SegQueue<T> {

// If the tail equals the head, that means the queue is empty.
if head >> SHIFT == tail >> SHIFT {
return Err(PopError);
return None;
}

// If head and tail are not in the same block, set `HAS_NEXT` in head.
Expand Down Expand Up @@ -355,7 +353,7 @@ impl<T> SegQueue<T> {
Block::destroy(block, offset + 1);
}

return Ok(value);
return Some(value);
},
Err(h) => {
head = h;
Expand Down
16 changes: 8 additions & 8 deletions crossbeam-queue/tests/array_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ fn smoke() {
let q = ArrayQueue::new(1);

q.push(7).unwrap();
assert_eq!(q.pop(), Ok(7));
assert_eq!(q.pop(), Some(7));

q.push(8).unwrap();
assert_eq!(q.pop(), Ok(8));
assert!(q.pop().is_err());
assert_eq!(q.pop(), Some(8));
assert!(q.pop().is_none());
}

#[test]
Expand Down Expand Up @@ -92,7 +92,7 @@ fn len() {
scope.spawn(|_| {
for i in 0..COUNT {
loop {
if let Ok(x) = q.pop() {
if let Some(x) = q.pop() {
assert_eq!(x, i);
break;
}
Expand Down Expand Up @@ -124,13 +124,13 @@ fn spsc() {
scope.spawn(|_| {
for i in 0..COUNT {
loop {
if let Ok(x) = q.pop() {
if let Some(x) = q.pop() {
assert_eq!(x, i);
break;
}
}
}
assert!(q.pop().is_err());
assert!(q.pop().is_none());
});

scope.spawn(|_| {
Expand All @@ -155,7 +155,7 @@ fn mpmc() {
scope.spawn(|_| {
for _ in 0..COUNT {
let n = loop {
if let Ok(x) = q.pop() {
if let Some(x) = q.pop() {
break x;
}
};
Expand Down Expand Up @@ -205,7 +205,7 @@ fn drops() {
scope(|scope| {
scope.spawn(|_| {
for _ in 0..steps {
while q.pop().is_err() {}
while q.pop().is_none() {}
}
});

Expand Down
14 changes: 7 additions & 7 deletions crossbeam-queue/tests/seg_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ use rand::{thread_rng, Rng};
fn smoke() {
let q = SegQueue::new();
q.push(7);
assert_eq!(q.pop(), Ok(7));
assert_eq!(q.pop(), Some(7));

q.push(8);
assert_eq!(q.pop(), Ok(8));
assert!(q.pop().is_err());
assert_eq!(q.pop(), Some(8));
assert!(q.pop().is_none());
}

#[test]
Expand Down Expand Up @@ -62,13 +62,13 @@ fn spsc() {
scope.spawn(|_| {
for i in 0..COUNT {
loop {
if let Ok(x) = q.pop() {
if let Some(x) = q.pop() {
assert_eq!(x, i);
break;
}
}
}
assert!(q.pop().is_err());
assert!(q.pop().is_none());
});
scope.spawn(|_| {
for i in 0..COUNT {
Expand All @@ -92,7 +92,7 @@ fn mpmc() {
scope.spawn(|_| {
for _ in 0..COUNT {
let n = loop {
if let Ok(x) = q.pop() {
if let Some(x) = q.pop() {
break x;
}
};
Expand Down Expand Up @@ -140,7 +140,7 @@ fn drops() {
scope(|scope| {
scope.spawn(|_| {
for _ in 0..steps {
while q.pop().is_err() {}
while q.pop().is_none() {}
}
});

Expand Down

0 comments on commit 69766ea

Please sign in to comment.