o3 0.33.2

shared-nothing primitives
Documentation
use std::marker;

use cycle::Policy;

use crate::depot::{
    arena::slab::{
        self, entries,
        key::{self, cycle},
        lookup,
        storage::{self, Plane},
    },
    capacity,
    capacity::Physical,
};

pub(in crate::depot) struct Occupied<
    'a,
    T,
    const MAX: u32,
    M: entries::Mode,
    const PARTITIONS: usize,
    S = storage::Heap,
> where
    S: storage::Storage,
{
    pub(in crate::depot) core: &'a entries::Core<T, MAX, M, PARTITIONS, S>,
    pub(in crate::depot) slot: &'a storage::Slot<T, MAX, M>,
}

impl<'a, T, const MAX: u32, const RECYCLE: bool, const PARTITIONS: usize, S>
    Occupied<'a, T, MAX, entries::Exclusive<RECYCLE>, PARTITIONS, S>
where
    cycle::Mode<RECYCLE>: Policy,
    S: storage::Storage,
{
    pub(in crate::depot) fn read(self) -> &'a T {
        // SAFETY: the admitted slot retains its exclusive owner's shared loan.
        unsafe { self.slot.value() }
    }
}

impl<'a, T, const MAX: u32, M: entries::Mode, const PARTITIONS: usize, S>
    Occupied<'a, T, MAX, M, PARTITIONS, S>
where
    S: storage::Storage,
{
    pub(in crate::depot) fn try_at(
        core: &'a entries::Core<T, MAX, M, PARTITIONS, S>,
        index: u32,
    ) -> lookup::Result<Self, M> {
        let slots = &core.slots;
        if index >= slots.built() {
            return Err(if index as usize >= slots.capacity() {
                lookup::Error::Index {
                    index,
                    capacity: slots.count(),
                }
            } else {
                lookup::Error::Free { index }
            });
        }
        // SAFETY: this index is within the owner's initialized backing prefix.
        let live = unsafe { crate::depot::raw::Proof::new((core, index)) };
        entries::Core::try_occupied(live)
    }
}

impl<'a, T, const MAX: u32, M: entries::Mode, const PARTITIONS: usize, S>
    Occupied<'a, T, MAX, M, PARTITIONS, S>
where
    S: storage::Storage,
{
    pub(in crate::depot) fn at(
        core: &'a entries::Core<T, MAX, M, PARTITIONS, S>,
        index: u32,
    ) -> Option<Self> {
        let slot = core.slots.get(index)?;
        if slot.state.get() != slab::State::Occupied {
            return None;
        }
        Some(Self { core, slot })
    }

    pub(in crate::depot) fn key(
        core: &'a entries::Core<T, MAX, M, PARTITIONS, S>,
        index: u32,
        epoch: key::Generation<MAX>,
    ) -> Option<Self> {
        let entry = Self::at(core, index)?;
        (entry.generation() == epoch).then_some(entry)
    }

    pub(in crate::depot) fn take(self) -> entries::Busy<'a, T, MAX, M, PARTITIONS, (), S> {
        if M::REENTRANT {
            self.slot.state.set(M::TAKEN);
        }
        entries::Busy {
            plane: marker::PhantomData,
            core: self.core,
            slot: self.slot,
        }
    }
}

impl<'a, T, const MAX: u32, M: entries::Mode, const PARTITIONS: usize, S>
    Occupied<'a, T, MAX, M, PARTITIONS, S>
where
    S: storage::Storage,
{
    pub(in crate::depot) fn try_key<Tag>(
        core: &'a entries::Core<T, MAX, M, PARTITIONS, S>,
        key: key::Handle<Tag, MAX>,
    ) -> Lookup<Self, Tag, MAX, M> {
        let slots = &core.slots;
        let slot = slots.get(key.index()).ok_or(key::Error::Index {
            key,
            capacity: slots.count(),
        })?;
        let actual = <M::Cycle as Policy>::generation(slot.generation.get());
        slot.state
            .get()
            .classify(actual, key.generation())
            .map_err(|refusal| key::Error::refused(key, actual, refusal))?;
        Ok(Self { core, slot })
    }

    pub(in crate::depot) fn generation(&self) -> key::Generation<MAX> {
        <M::Cycle as Policy>::generation(self.slot.generation.get())
    }
}

impl<'a, T, const MAX: u32> Occupied<'a, T, MAX, entries::Exclusive<false>, 1> {
    pub(in crate::depot) fn try_bound<'h, Tag>(
        proof: PhysicalSlot<'a, 'h, T, Tag, MAX>,
    ) -> Result<Self, key::Stale<'h, Tag, MAX>> {
        let (core, key) = proof.into_inner();
        let slots = core.slots.as_ref();
        // SAFETY: the retained bound selects this eager owner's initialized extent.
        let slot = unsafe { slots.get_unchecked(key.as_inner().index() as usize) };
        let actual = slot.generation.get();
        slot.state
            .get()
            .classify(actual, key.as_inner().generation())
            .map_err(|refusal| key::Stale::refused(key, actual, refusal))?;
        Ok(Self { core, slot })
    }
}

type Lookup<S, T, const MAX: u32, M> = Result<
    S,
    key::Error<
        T,
        MAX,
        <M as entries::Mode>::Busy,
        <<M as entries::Mode>::Cycle as Policy>::Retired,
    >,
>;

type PhysicalSlot<'a, 'h, T, Tag, const MAX: u32> = crate::depot::raw::Proof<
    (
        &'a entries::Core<T, MAX, entries::Exclusive<false>, 1>,
        capacity::Key<'h, key::Handle<Tag, MAX>>,
    ),
    Physical,
>;