ubq 7.0.0

Lock-free unbounded MPMC queue with no_std + alloc support.
use crate::{block::MpmcBlock as Block, page::page_size};
use core::ptr;

#[derive(Clone, Copy, Debug)]
pub(crate) struct HeadCodec {
    block_length: usize,
    pointer_mask: usize,
    index_mask: usize,
    has_next_mask: usize,
}

impl HeadCodec {
    pub(crate) fn new<T>() -> Self {
        let page_size = page_size();
        let block_length = Block::<T>::capacity();
        let page_bits = page_size.trailing_zeros();
        let index_bits = usize::BITS - block_length.leading_zeros();

        assert!(
            index_bits <= page_bits,
            "the block index does not fit in the page-aligned pointer tag"
        );

        let index_mask = usize::MAX >> (usize::BITS - index_bits);
        let has_next_mask = if index_bits < page_bits {
            1usize << index_bits
        } else {
            // A maximal one-byte slot layout can consume every page-alignment
            // bit. `has_next` is only a cache hint, so dropping it is correct.
            0
        };

        Self {
            block_length,
            pointer_mask: !(page_size - 1),
            index_mask,
            has_next_mask,
        }
    }

    #[inline]
    pub(crate) const fn block_length(self) -> usize {
        self.block_length
    }

    #[cfg(test)]
    const fn has_next_enabled(self) -> bool {
        self.has_next_mask != 0
    }
}

pub(crate) struct Head<T> {
    pub(crate) block: *mut Block<T>,
    pub(crate) index: usize,
    pub(crate) has_next: bool,
}

impl<T> Head<T> {
    pub(crate) const ZERO: Self = Self {
        block: ptr::null_mut(),
        index: 0,
        has_next: false,
    };

    pub(crate) const fn from_ptr(block: *mut Block<T>) -> Self {
        Self {
            block,
            ..Self::ZERO
        }
    }

    #[inline]
    pub(crate) fn from_usize(value: usize, codec: HeadCodec) -> Self {
        Self {
            block: ptr::with_exposed_provenance_mut(value & codec.pointer_mask),
            index: value & codec.index_mask,
            has_next: codec.has_next_mask != 0 && value & codec.has_next_mask != 0,
        }
    }

    #[inline]
    pub(crate) fn to_usize(self, codec: HeadCodec) -> usize {
        debug_assert_eq!(self.block.addr() & !codec.pointer_mask, 0);
        debug_assert!(self.index <= codec.block_length);

        self.block.expose_provenance()
            | (self.index & codec.index_mask)
            | (if self.has_next {
                codec.has_next_mask
            } else {
                0
            })
    }

    pub(crate) const fn is_zero(&self) -> bool {
        self.block.is_null() && self.index == 0 && !self.has_next
    }
}

impl<T> Copy for Head<T> {}

impl<T> Clone for Head<T> {
    fn clone(&self) -> Self {
        *self
    }
}

#[cfg(test)]
mod tests {
    use super::{Head, HeadCodec};
    use crate::block::MpmcBlock as Block;

    #[test]
    fn codec_round_trips_the_page_aligned_block_and_index() {
        let codec = HeadCodec::new::<u64>();
        let length = codec.block_length();
        assert!(codec.has_next_enabled());

        let block = Block::<u64>::new();
        let head = Head {
            block,
            index: length,
            has_next: true,
        };
        let decoded = Head::from_usize(head.to_usize(codec), codec);
        assert_eq!(decoded.block, block);
        assert_eq!(decoded.index, length);
        assert!(decoded.has_next);
        Block::free(block);
    }
}