diff --git a/src/lib.rs b/src/lib.rs index 8b495ce..a4d26b5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -75,6 +75,24 @@ mod unbounded; mod sync; +/// Make the given function const if the given condition is true. +macro_rules! const_fn { + ( + const_if: #[cfg($($cfg:tt)+)]; + $(#[$($attr:tt)*])* + $vis:vis const fn $($rest:tt)* + ) => { + #[cfg($($cfg)+)] + $(#[$($attr)*])* + $vis const fn $($rest)* + #[cfg(not($($cfg)+))] + $(#[$($attr)*])* + $vis fn $($rest)* + }; +} + +pub(crate) use const_fn; + /// A concurrent queue. /// /// # Examples @@ -131,18 +149,21 @@ impl ConcurrentQueue { } } - /// Creates a new unbounded queue. - /// - /// # Examples - /// - /// ``` - /// use concurrent_queue::ConcurrentQueue; - /// - /// let q = ConcurrentQueue::::unbounded(); - /// ``` - pub fn unbounded() -> ConcurrentQueue { - ConcurrentQueue(Inner::Unbounded(Unbounded::new())) - } + const_fn!( + const_if: #[cfg(not(loom))]; + /// Creates a new unbounded queue. + /// + /// # Examples + /// + /// ``` + /// use concurrent_queue::ConcurrentQueue; + /// + /// let q = ConcurrentQueue::::unbounded(); + /// ``` + pub const fn unbounded() -> ConcurrentQueue { + ConcurrentQueue(Inner::Unbounded(Unbounded::new())) + } + ); /// Attempts to push an item into the queue. /// diff --git a/src/unbounded.rs b/src/unbounded.rs index a84f856..8e1c40d 100644 --- a/src/unbounded.rs +++ b/src/unbounded.rs @@ -4,6 +4,7 @@ use core::ptr; use crossbeam_utils::CachePadded; +use crate::const_fn; use crate::sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; use crate::sync::cell::UnsafeCell; #[allow(unused_imports)] @@ -148,19 +149,22 @@ pub struct Unbounded { } impl Unbounded { - /// Creates a new unbounded queue. - pub fn new() -> Unbounded { - Unbounded { - head: CachePadded::new(Position { - block: AtomicPtr::new(ptr::null_mut()), - index: AtomicUsize::new(0), - }), - tail: CachePadded::new(Position { - block: AtomicPtr::new(ptr::null_mut()), - index: AtomicUsize::new(0), - }), + const_fn!( + const_if: #[cfg(not(loom))]; + /// Creates a new unbounded queue. + pub const fn new() -> Unbounded { + Unbounded { + head: CachePadded::new(Position { + block: AtomicPtr::new(ptr::null_mut()), + index: AtomicUsize::new(0), + }), + tail: CachePadded::new(Position { + block: AtomicPtr::new(ptr::null_mut()), + index: AtomicUsize::new(0), + }), + } } - } + ); /// Pushes an item into the queue. pub fn push(&self, value: T) -> Result<(), PushError> {