o3 0.16.2

shared-nothing primitives
Documentation
use std::{cell, ptr};

use pool::state;

use crate::buffer::{self, pool};

const NONE: u32 = u32::MAX;

#[repr(C)]
pub(super) struct Core {
    pub(super) refs: crate::cell::LocalRefCount,
    pub(super) free: cell::Cell<u32>,
    pub(super) free_len: cell::Cell<u32>,
    pub(super) slots: u32,
    pub(super) capacity: u32,
    pub(super) data_offset: usize,
    pub(super) allocation_size: usize,
}

#[repr(C)]
pub(super) struct Slot {
    pub(super) refs: crate::cell::LocalRefCount,
    pub(super) next: cell::Cell<u32>,
}

const _: () = assert!(align_of::<Core>() >= align_of::<Slot>());

impl Core {
    pub(super) fn allocate<S: state::State>(layout: buffer::Layout) -> ptr::NonNull<Self> {
        match Self::try_allocate::<S>(layout) {
            Ok(core) => core,
            Err(_) => {
                use std::alloc::handle_alloc_error;
                handle_alloc_error(layout.allocation())
            }
        }
    }

    pub(super) fn try_allocate<S: state::State>(
        layout: buffer::Layout,
    ) -> Result<ptr::NonNull<Self>, pool::AllocationError> {
        let raw = if S::ZEROED {
            unsafe {
                use std::alloc::alloc_zeroed;
                alloc_zeroed(layout.allocation())
            }
        } else {
            unsafe {
                use std::alloc::alloc;
                alloc(layout.allocation())
            }
        };
        let ptr = ptr::NonNull::new(raw.cast::<Self>()).ok_or(pool::AllocationError)?;
        unsafe {
            ptr.write(Self {
                refs: crate::cell::LocalRefCount::one(),
                free: cell::Cell::new(if layout.slot_count() == 0 { NONE } else { 0 }),
                free_len: cell::Cell::new(layout.slot_count()),
                slots: layout.slot_count(),
                capacity: layout.capacity().get(),
                data_offset: layout.data_offset(),
                allocation_size: layout.allocation().size(),
            });
            let slot_ptr = ptr
                .as_ptr()
                .cast::<u8>()
                .add(size_of::<Self>())
                .cast::<Slot>();
            for index in 0..layout.slot_count() {
                slot_ptr.add(index as usize).write(Slot {
                    refs: crate::cell::LocalRefCount::empty(),
                    next: cell::Cell::new(if index + 1 == layout.slot_count() {
                        NONE
                    } else {
                        index + 1
                    }),
                });
            }
        }
        Ok(ptr)
    }

    pub(super) fn acquire(ptr: ptr::NonNull<Self>) -> Option<u32> {
        let core = unsafe { ptr.as_ref() };
        let index = core.free.get();
        if index == NONE {
            return None;
        }
        core.refs.retain();
        let slot = unsafe { &*Self::slot(ptr, index) };
        debug_assert!(slot.refs.is_empty());
        core.free.set(slot.next.get());
        core.free_len.set(core.free_len.get() - 1);
        slot.refs.activate();
        Some(index)
    }

    pub(super) fn slot(ptr: ptr::NonNull<Self>, index: u32) -> *mut Slot {
        let core = unsafe { ptr.as_ref() };
        debug_assert!(index < core.slots);
        unsafe {
            ptr.as_ptr()
                .cast::<u8>()
                .add(size_of::<Self>())
                .cast::<Slot>()
                .add(index as usize)
        }
    }

    pub(super) fn data(ptr: ptr::NonNull<Self>, index: u32) -> *mut u8 {
        let core = unsafe { ptr.as_ref() };
        debug_assert!(index < core.slots);
        unsafe {
            ptr.as_ptr()
                .cast::<u8>()
                .add(core.data_offset + index as usize * core.capacity as usize)
        }
    }
}