dope-core 0.15.1

The manifold runtime
Documentation
use std::{mem, ptr};

use o3::{buffer::resident, permit};

use crate::{driver, io};

pub(in crate::io::recv) struct Owner<'d> {
    lease: permit::Lease<ReturnBuffer<'d>>,
}

struct ReturnBuffer<'d> {
    driver: driver::Reference<'d>,
}

impl permit::Return for ReturnBuffer<'_> {
    type Item = io::Buffer;

    fn return_item(&self, buffer: Self::Item) {
        self.driver.maintenance().return_buffer(buffer);
    }
}

pub(in crate::io::recv) trait Proof<'d> {
    fn into_parts(
        self,
    ) -> (
        driver::Reference<'d>,
        driver::RecvOwner<'d>,
        super::raw::Region,
    );
}

impl<'d> Owner<'d> {
    pub(in crate::io::recv) fn new(driver: driver::Reference<'d>, buffer: io::Buffer) -> Self {
        Self {
            lease: permit::Lease::new(ReturnBuffer { driver }, buffer),
        }
    }

    fn into_parts(self) -> (driver::Reference<'d>, io::Buffer) {
        let (return_buffer, buffer) = self.lease.into_parts();
        (return_buffer.driver, buffer)
    }

    pub(in crate::io::recv) fn share(self) -> (driver::Reference<'d>, driver::RecvOwner<'d>) {
        let (driver, buffer) = self.into_parts();
        let owner = driver.receive().retain_buffer(buffer);
        (driver, owner)
    }

    pub(in crate::io::recv) fn retain(
        self,
        budget: &resident::Budget<'d>,
    ) -> Result<(driver::Reference<'d>, driver::AccountedRecvOwner<'d>), Self> {
        let (driver, buffer) = self.into_parts();
        match driver.receive().retain_accounted_buffer(buffer, budget) {
            Ok(owner) => Ok((driver, owner)),
            Err(buffer) => Err(Self::new(driver, buffer)),
        }
    }
}

const _: () = {
    assert!(
        mem::size_of::<Owner<'static>>()
            == mem::size_of::<(driver::Reference<'static>, io::Buffer)>()
    );
    assert!(
        mem::align_of::<Owner<'static>>()
            == mem::align_of::<(driver::Reference<'static>, io::Buffer)>()
    );
};

impl<'d> Proof<'d> for super::Unique<'d> {
    fn into_parts(
        self,
    ) -> (
        driver::Reference<'d>,
        driver::RecvOwner<'d>,
        super::raw::Region,
    ) {
        let this = mem::ManuallyDrop::new(self);
        let owner = unsafe { ptr::read(&this.owner) };
        let region = unsafe { ptr::read(&this.region) };
        (this.driver, owner, region)
    }
}