Skip to content

Commit

Permalink
feat: Make unbounded a const function
Browse files Browse the repository at this point in the history
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 smol-rs/async-executor#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>
  • Loading branch information
james7132 and taiki-e committed Apr 13, 2024
1 parent 59e93fc commit 89a64f8
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 24 deletions.
45 changes: 33 additions & 12 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
///
Expand Down
28 changes: 16 additions & 12 deletions src/unbounded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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>> {
Expand Down

0 comments on commit 89a64f8

Please sign in to comment.