o3 0.14.0

shared-nothing primitives
Documentation
use std::mem;

use crate::collections::slab::{self, core};

pub(in crate::collections::slab) struct Busy<'a, T, G: slab::GenerationState, M: core::Mode> {
    core: &'a core::Core<T, G, M>,
    index: core::SlotIndex,
    generation: G,
    live: bool,
}

impl<'a, T, G: slab::GenerationState, M: core::Mode> Busy<'a, T, G, M> {
    pub(in crate::collections::slab) fn take_committed(
        core: &'a core::Core<T, G, M>,
        ticket: core::Ticket<G>,
    ) -> Self {
        let slot = unsafe { core.slots.get_unchecked(ticket.index.get() as usize) };
        debug_assert!(
            slot.state.get() == core::State::Occupied && slot.generation.get() == ticket.generation
        );
        if M::REENTRANT {
            slot.state.set(core::State::Busy);
        }
        Self {
            core,
            index: ticket.index,
            generation: ticket.generation,
            live: true,
        }
    }

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

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

    pub(in crate::collections::slab) fn index(&self) -> u32 {
        self.index.get()
    }

    pub(in crate::collections::slab) fn generation(&self) -> G {
        self.generation
    }

    pub(in crate::collections::slab) fn value(&self) -> &T {
        unsafe { self.slot().value() }
    }

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

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

    pub(in crate::collections::slab) fn commit_removal(mut self) -> (T, core::SlotIndex) {
        let next = self.generation.next();
        let value = unsafe { self.slot().take_value() };
        self.live = false;
        self.core.entries().remove_occupied(self.index);
        match next {
            Some(generation) => self.core.reservations().release(self.index, generation),
            None if self.core.recycle_generations() => {
                self.core.reservations().release(self.index, G::MIN)
            }
            None => self.slot().state.set(core::State::Retired),
        }
        (value, self.index)
    }
}

pub(super) struct Inserted<'a, T, G: slab::GenerationState, M: core::Mode> {
    busy: mem::ManuallyDrop<Busy<'a, T, G, M>>,
    rollback: bool,
}

impl<'a, T, G: slab::GenerationState, M: core::Mode> Inserted<'a, T, G, M> {
    pub(super) fn new(core: &'a core::Core<T, G, M>, ticket: core::Ticket<G>) -> Self {
        Self {
            busy: mem::ManuallyDrop::new(Busy::take_committed(core, ticket)),
            rollback: true,
        }
    }

    pub(super) fn value_mut(&mut self) -> &mut T {
        self.busy.value_mut()
    }

    pub(super) fn commit(mut self) {
        self.rollback = false;
        unsafe { mem::ManuallyDrop::drop(&mut self.busy) };
    }

    pub(super) fn rollback(mut self) -> T {
        self.rollback = false;
        unsafe { mem::ManuallyDrop::take(&mut self.busy) }
            .commit_removal()
            .0
    }
}

impl<T, G: slab::GenerationState, M: core::Mode> Drop for Inserted<'_, T, G, M> {
    fn drop(&mut self) {
        if self.rollback {
            let busy = unsafe { mem::ManuallyDrop::take(&mut self.busy) };
            drop(busy.commit_removal().0);
        }
    }
}

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