dope-core 0.15.0

The manifold runtime
Documentation
use std::marker;

use o3::mem::quota;

use crate::driver::schedule::{self, ready, timer};

struct Domain<'d>(marker::PhantomData<fn(&'d ()) -> &'d ()>);
struct BudgetTag<'d, Lane> {
    driver: marker::PhantomData<fn(&'d ()) -> &'d ()>,
    lane: marker::PhantomData<fn(Lane) -> Lane>,
}

#[must_use = "unused scheduler quota is returned when the quota is dropped"]
#[repr(transparent)]
pub(crate) struct Quota<'turn, 'd> {
    inner: quota::Shared<'turn, Domain<'d>>,
}

#[must_use = "unused scheduler budget is returned when the budget is dropped"]
#[repr(transparent)]
pub(crate) struct Budget<'turn, 'd, Lane> {
    inner: quota::Lease<'turn, BudgetTag<'d, Lane>>,
}

impl<'turn, 'd> Quota<'turn, 'd> {
    pub(super) fn from_reactor(ledger: &'turn quota::Ledger<super::ReactorLane>) -> Self {
        Self {
            inner: quota::Shared::reserve_all(ledger),
        }
    }

    pub(super) fn from_application(
        work: super::Application<'turn, 'd>,
        count: usize,
    ) -> Option<Self> {
        Some(Self {
            inner: quota::Shared::reserve_exact(work.remaining, count)?,
        })
    }

    pub(super) fn from_maintenance(work: super::Maintenance<'turn, 'd>, limit: usize) -> Self {
        Self {
            inner: quota::Shared::reserve_up_to(&work.work.maintenance, limit),
        }
    }

    pub(super) fn reserve_budget<'quota, Lane>(
        &'quota self,
        limit: usize,
    ) -> Budget<'quota, 'd, Lane> {
        Budget {
            inner: self.inner.lease_up_to(limit),
        }
    }

    pub(crate) fn remaining(&self) -> usize {
        self.inner.remaining()
    }

    pub(crate) fn spend(&mut self, count: usize) {
        self.inner.spend(count);
    }
}

impl<'turn, 'd> Budget<'turn, 'd, ready::Lane> {
    pub(super) fn from_ready(work: super::Turn<'turn, 'd>, limit: usize) -> Self {
        Self {
            inner: quota::Lease::reserve_up_to(&work.work.ready, limit),
        }
    }
}

impl<'turn, 'd> Budget<'turn, 'd, timer::Lane> {
    pub(super) fn from_timers(work: super::Timers<'turn, 'd>) -> Self {
        Self {
            inner: quota::Lease::reserve_all(work.remaining),
        }
    }
}

impl<Lane> Budget<'_, '_, Lane> {
    pub(crate) const fn remaining(&self) -> usize {
        self.inner.remaining()
    }

    pub(crate) fn take(&mut self) -> bool {
        if self.inner.remaining() == 0 {
            return false;
        }
        self.spend(1);
        true
    }

    pub(crate) fn spend(&mut self, count: usize) {
        self.inner.spend(count);
    }

    pub(crate) fn admit_with<T>(
        &mut self,
        acquire: impl FnOnce() -> Option<T>,
    ) -> schedule::Admission<T> {
        match self.inner.admit_with(acquire) {
            quota::Admission::Item(value) => schedule::Admission::Item(value),
            quota::Admission::Empty => schedule::Admission::Empty,
            quota::Admission::Exhausted => schedule::Admission::Exhausted,
        }
    }
}

const _: () =
    assert!(std::mem::size_of::<Quota<'static, 'static>>() == 2 * std::mem::size_of::<usize>());
const _: () = assert!(
    std::mem::size_of::<Budget<'static, 'static, ()>>() == 2 * std::mem::size_of::<usize>()
);
const _: () =
    assert!(std::mem::size_of::<schedule::Admission<usize>>() == 2 * std::mem::size_of::<usize>());