feat: Make unbounded a const function
This PR makes `ConcurrentQueue::unbounded` a const function. It'd be great if `bounded` could be `const` as well, but this would likely require static memory allocation support in const functions, which is currently not allowed by the compiler. This would enable https://github.com/smol-rs/async-executor/pull/112 to be directly constructable in a const context (i.e. static/thread_local variable initialization without OnceLock). It might also allow unbounded `async_channel`s to be constructed in a similar context. Co-authored-by: Taiki Endo <te316e89@gmail.com>
This commit is contained in:
parent
59e93fc952
commit
89a64f8c3b
45
src/lib.rs
45
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<T> ConcurrentQueue<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Creates a new unbounded queue.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use concurrent_queue::ConcurrentQueue;
|
||||
///
|
||||
/// let q = ConcurrentQueue::<i32>::unbounded();
|
||||
/// ```
|
||||
pub fn unbounded() -> ConcurrentQueue<T> {
|
||||
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::<i32>::unbounded();
|
||||
/// ```
|
||||
pub const fn unbounded() -> ConcurrentQueue<T> {
|
||||
ConcurrentQueue(Inner::Unbounded(Unbounded::new()))
|
||||
}
|
||||
);
|
||||
|
||||
/// Attempts to push an item into the queue.
|
||||
///
|
||||
|
|
|
@ -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<T> {
|
|||
}
|
||||
|
||||
impl<T> Unbounded<T> {
|
||||
/// Creates a new unbounded queue.
|
||||
pub fn new() -> Unbounded<T> {
|
||||
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<T> {
|
||||
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<T>> {
|
||||
|
|
Loading…
Reference in New Issue