Skip to main content

o3/buffer/pool/owners/edge/
mod.rs

1pub(in crate::buffer) use input::Measured;
2
3use crate::buffer::{pool::owners, storage::regions};
4
5mod input;
6
7use std::{marker, mem, ptr};
8
9use crate::{buffer, buffer::pool, mem::rc};
10
11/// One exact live pool-slot edge with its backing and root mode preserved.
12#[derive(Debug)]
13#[repr(transparent)]
14pub struct Edge<K: crate::buffer::raw::Backing = owners::Plain, M = pool::Owned> {
15    ptr: Option<ptr::NonNull<regions::Prefix>>,
16    mode: marker::PhantomData<(K, M)>,
17}
18
19impl<K: crate::buffer::raw::Backing, M> Edge<K, M> {
20    pub(in crate::buffer) const NONE: Self = Self {
21        ptr: None,
22        mode: marker::PhantomData,
23    };
24
25    pub(in crate::buffer::pool) const fn new(ptr: ptr::NonNull<regions::Prefix>) -> Self {
26        Self {
27            ptr: Some(ptr),
28            mode: marker::PhantomData,
29        }
30    }
31
32    pub(in crate::buffer) fn into_raw(self) -> Option<ptr::NonNull<regions::Prefix>> {
33        let this = mem::ManuallyDrop::new(self);
34        this.ptr
35    }
36
37    pub(in crate::buffer) unsafe fn release_raw(ptr: ptr::NonNull<()>) {
38        use crate::mem::raw::Edge;
39
40        // SAFETY: callers transfer one live pool-slot prefix edge.
41        if unsafe { ptr.cast::<regions::Prefix>().as_ref().release() } != rc::Release::Last {
42            return;
43        }
44        // SAFETY: Last transfers the exact terminal slot edge into Retired.
45        unsafe { owners::Retired::<K, owners::Any>::from_owner(ptr) }.finish();
46    }
47}
48
49impl<L> Edge<owners::Plain<L>, pool::Borrowed<'_>> {
50    pub(in crate::buffer) fn into_owned(self) -> Edge<owners::Plain<L>, pool::Owned> {
51        let this = mem::ManuallyDrop::new(self);
52        Edge {
53            ptr: this.ptr,
54            mode: marker::PhantomData,
55        }
56    }
57}
58
59impl<K: crate::buffer::raw::Backing, M> Drop for Edge<K, M> {
60    fn drop(&mut self) {
61        if let Some(ptr) = self.ptr {
62            // SAFETY: Edge owns exactly one live pool-slot prefix edge.
63            unsafe { Self::release_raw(ptr.cast()) };
64        }
65    }
66}
67
68// SAFETY: retaining Edge creates one edge for the same exact pool slot and
69// preserves both its backing kind and root-mode lifetime.
70unsafe impl<K: crate::buffer::raw::Backing, M> buffer::raw::Retain for Edge<K, M> {
71    fn try_retain(&self) -> Result<Self, rc::Error> {
72        use crate::mem::raw::Edge;
73
74        let pointer = self.ptr;
75        if let Some(ptr) = pointer {
76            // SAFETY: the borrowed Edge proves this slot prefix is active.
77            unsafe { ptr.as_ref().try_retain() }?;
78        }
79        Ok(Self {
80            ptr: pointer,
81            mode: marker::PhantomData,
82        })
83    }
84}
85
86const _: () = {
87    assert!(size_of::<Edge>() == size_of::<usize>());
88    assert!(size_of::<Edge<owners::Plain, pool::Borrowed<'static>>>() == size_of::<usize>());
89    assert!(size_of::<Edge<owners::Resident<'static>>>() == size_of::<usize>());
90};
91
92impl<K: crate::buffer::raw::Backing, M> regions::End for Edge<K, M> {
93    const EMPTY: Option<Self> = Some(Self::NONE);
94}
95
96impl<K: crate::buffer::raw::Backing, M> buffer::Residency for owners::Edge<K, M> {
97    fn resident(&self) -> usize {
98        self.ptr.map_or(0, |ptr| {
99            // SAFETY: Edge retains this exact active pool-slot prefix.
100            unsafe { owners::capacity_of(ptr.cast()) }.get() as usize
101        })
102    }
103}