dope-core 0.15.1

The manifold runtime
Documentation
use std::{io, process};

use o3::collections::batch::set;

use crate::{
    backend::uring::{self, engine::lifecycle},
    driver::route,
    io::fd::handles,
};

pub(super) struct Maintenance {
    deferred_close: set::Set,
    slots: usize,
}

impl Maintenance {
    pub(super) fn new(capacity: usize) -> io::Result<Self> {
        let entries = capacity.checked_mul(2).ok_or_else(|| {
            io::Error::new(
                io::ErrorKind::InvalidInput,
                "dope-uring: lifecycle maintenance capacity overflow",
            )
        })?;
        Ok(Self {
            deferred_close: set::Set::try_with_capacity(entries)?,
            slots: capacity,
        })
    }

    pub(super) fn schedule_close(&mut self, work: super::CloseWork) {
        let index = work.slot().raw() as usize + if work.retires_slot() { self.slots } else { 0 };
        if !self.deferred_close.insert(index) {
            process::abort();
        }
    }

    pub(super) fn pending(&self) -> bool {
        !self.deferred_close.is_empty()
    }

    pub(super) fn maintain_one(
        &mut self,
        push: impl FnOnce(super::Maintenance) -> Result<(), super::Maintenance>,
    ) -> uring::MaintenanceStep {
        let Some(work) = self.pop_close() else {
            process::abort();
        };
        if let Err(super::Maintenance::Close(work)) = push(super::Maintenance::Close(work)) {
            self.schedule_close(work);
            return uring::MaintenanceStep::Blocked;
        }
        uring::MaintenanceStep::Progress
    }

    pub(super) fn pop_close(&mut self) -> Option<lifecycle::CloseWork> {
        let index = self.deferred_close.pop()?;
        if index < self.slots {
            let slot = route::SlotIndex::from_bounded(index as u32);
            Some(lifecycle::CloseWork::untracked(
                handles::FixedSlot::from_index(slot),
            ))
        } else {
            let raw = index - self.slots;
            let slot = route::SlotIndex::from_bounded(raw as u32);
            Some(lifecycle::CloseWork::retired(
                handles::FixedSlot::from_index(slot),
            ))
        }
    }
}