o3 0.7.0

shared-nothing primitives
Documentation
use super::{Mode, SlabCore, Slot, SlotIndex, State};
use crate::collections::slab::GenerationState;

pub(super) struct Busy<'a, T, G: GenerationState, M: Mode> {
    core: &'a SlabCore<T, G, M>,
    index: SlotIndex,
    generation: G,
    live: bool,
}

impl<'a, T, G: GenerationState, M: Mode> Busy<'a, T, G, M> {
    pub(super) fn take(core: &'a SlabCore<T, G, M>, index: u32) -> Option<Self> {
        let slot = core.slots.get(index as usize)?;
        let index = SlotIndex::new(index, core.slots.len())?;
        let state = if M::REENTRANT {
            slot.state.replace(State::Busy)
        } else {
            slot.state.get()
        };
        if state == State::Occupied {
            Some(Self {
                core,
                index,
                generation: slot.generation.get(),
                live: true,
            })
        } else {
            slot.state.set(state);
            None
        }
    }

    pub(super) fn take_key(core: &'a SlabCore<T, G, M>, index: u32, generation: G) -> Option<Self> {
        let busy = Self::take(core, index)?;
        (busy.generation == generation).then_some(busy)
    }

    pub(super) fn generation(&self) -> G {
        self.generation
    }

    pub(super) fn value_mut(&mut self) -> &mut T {
        unsafe {
            &mut *self
                .core
                .slots
                .get_unchecked(self.index.get() as usize)
                .value_ptr()
        }
    }

    fn slot(&self) -> &Slot<T, G> {
        unsafe { self.core.slots.get_unchecked(self.index.get() as usize) }
    }

    pub(super) fn commit_removal(mut self) -> (T, SlotIndex) {
        let next = self.generation.next();
        let value = unsafe { self.slot().take_value() };
        self.live = false;
        self.core.remove_occupied(self.index);
        match next {
            Some(generation) => self.core.release(self.index, generation),
            None => self.slot().state.set(State::Retired),
        }
        (value, self.index)
    }
}

impl<T, G: GenerationState, M: Mode> Drop for Busy<'_, T, G, M> {
    fn drop(&mut self) {
        if self.live && M::REENTRANT {
            self.slot().state.set(State::Occupied);
        }
    }
}