Skip to main content

base_scheduler/
buffer_lease.rs

1// Released under the MIT License.
2// Copyright, 2026, by Samuel Williams.
3
4use crate::{FrozenBuffer, IoBuf, IoBufMut, heap_buffer_pool::Slab};
5use std::{ops::Range, ptr::NonNull, sync::atomic::Ordering};
6
7/// An exclusive writable pool lease. Its initialized length can be shortened after a read, without copying or borrowing the receiver. Drop returns storage to the pool; an I/O backend must retain this owner until its access retires. A lease keeps its backing slab alive even after the pool is dropped.
8pub struct BufferLease {
9    slab: Option<NonNull<Slab>>,
10    index: usize,
11    length: usize,
12}
13
14impl BufferLease {
15    pub(crate) fn new(slab: NonNull<Slab>, index: usize, length: usize) -> Self {
16        Self {
17            slab: Some(slab),
18            index,
19            length,
20        }
21    }
22
23    /// Limit the visible initialized prefix. Panics if the requested length exceeds the current prefix.
24    pub fn truncate(&mut self, length: usize) {
25        assert!(length <= self.length, "buffer length out of bounds");
26        self.length = length;
27    }
28
29    /// Transfer this lease into immutable, independently retainable storage. No allocation or payload copy is required.
30    pub fn freeze(mut self) -> FrozenBuffer {
31        let slab = self.slab.take().unwrap();
32        // SAFETY: This lease owns the slot's persistent slab claim.
33        unsafe { slab.as_ref() }.slots[self.index]
34            .readers
35            .store(1, Ordering::Relaxed);
36        FrozenBuffer::new(
37            slab,
38            self.index,
39            Range {
40                start: 0,
41                end: self.length,
42            },
43        )
44    }
45}
46
47impl AsRef<[u8]> for BufferLease {
48    fn as_ref(&self) -> &[u8] {
49        // SAFETY: This lease owns its slot's persistent slab claim; the allocation and initialized prefix remain stable until release.
50        let slab = unsafe { self.slab.unwrap().as_ref() };
51        unsafe { std::slice::from_raw_parts(slab.pointer(self.index), self.length) }
52    }
53}
54impl AsMut<[u8]> for BufferLease {
55    fn as_mut(&mut self) -> &mut [u8] {
56        // SAFETY: The unique lease and exclusive borrow prevent other accesses to this slot. Frozen views cannot coexist with a mutable lease.
57        let slab = unsafe { self.slab.unwrap().as_ref() };
58        unsafe { std::slice::from_raw_parts_mut(slab.pointer(self.index), self.length) }
59    }
60}
61impl Drop for BufferLease {
62    fn drop(&mut self) {
63        if let Some(slab) = self.slab.take() {
64            // SAFETY: Drop consumes the unique mutable slot claim.
65            unsafe { Slab::release(slab, self.index) };
66        }
67    }
68}
69
70// SAFETY: Pool storage is initialized, fixed in size, and stable as its exclusive lease moves. Only the owned lease permits mutation; operations retain it through retirement.
71unsafe impl IoBuf for BufferLease {}
72unsafe impl IoBufMut for BufferLease {}
73
74// SAFETY: The owned slot claim keeps the slab alive, and only an exclusive borrow permits writes.
75unsafe impl Send for BufferLease {}
76unsafe impl Sync for BufferLease {}
77
78impl std::fmt::Debug for BufferLease {
79    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80        formatter
81            .debug_struct("BufferLease")
82            .field("length", &self.length)
83            .finish_non_exhaustive()
84    }
85}
86
87impl crate::ReceiveBuffer for BufferLease {
88    type Frozen = FrozenBuffer;
89    fn truncate(&mut self, length: usize) {
90        BufferLease::truncate(self, length);
91    }
92    fn freeze(self) -> FrozenBuffer {
93        BufferLease::freeze(self)
94    }
95}