pub struct DeviceBuffer { /* private fields */ }Expand description
An owning handle to a single device allocation.
§Ownership & lifetime
A DeviceBuffer is the sole owner of the allocation it names. It is
produced only by ExecutionProvider::allocate and released only by
ExecutionProvider::deallocate, which consumes it by value. The owning
EP is both allocator and deallocator: the buffer records the DeviceId
(hence which EP instance) that may free it, so a buffer must never be handed
to a different EP. Ownership is unique — no two DeviceBuffers ever alias
the same allocation.
§No Drop
DeviceBuffer deliberately does not implement Drop. Freeing device
memory generally needs the EP’s context/stream (a CUDA context, an MLX
queue, an allocator arena) that this bare handle does not carry, so a silent
drop could not free correctly. Consequences:
- Dropping a
DeviceBufferwithout passing it todeallocateleaks the allocation. It can never double-free, which is the memory-safety property we prioritize (plan §4.4). - The session layer owns the discipline of pairing every
allocatewith exactly onedeallocate. Higher layers may wrap this handle in an RAII/Arctype that calls back into the EP; that policy lives above the EP contract, not here.
§Access
The base address is reachable only through DeviceBuffer::as_ptr
(shared) and DeviceBuffer::as_mut_ptr (unique). Obtaining a pointer is
safe; dereferencing it is unsafe and valid only on host-accessible
devices (DeviceType::is_host_accessible) within the owning EP’s context.
§Thread-safety
See the Send/Sync impls below for the exact invariant.
Implementations§
Source§impl DeviceBuffer
impl DeviceBuffer
Sourcepub unsafe fn from_raw_parts(
ptr: *mut c_void,
device: DeviceId,
size: usize,
align: usize,
) -> Self
pub unsafe fn from_raw_parts( ptr: *mut c_void, device: DeviceId, size: usize, align: usize, ) -> Self
Wrap a raw device allocation in an owning handle.
§Safety
The caller (the owning EP) must guarantee all of:
ptris non-null and points to the start of an allocation of at leastsizebytes ondevice, aligned to at leastalignbytes.- The allocation was produced by
device’s EP and will be freed exactly once, only by returning this handle to that EP’sdeallocate(or via an equivalent raw free of the pointer obtained fromDeviceBuffer::into_raw). - No other live
DeviceBufferaliases the same allocation.
align must be a power of two (checked in debug builds).
Sourcepub fn device(&self) -> DeviceId
pub fn device(&self) -> DeviceId
The device this allocation lives on (and whose EP must free it).
Sourcepub fn as_ptr(&self) -> *const c_void
pub fn as_ptr(&self) -> *const c_void
Shared base pointer. Safe to obtain; dereferencing is unsafe and only
sound on host-accessible devices within the owning EP’s context.
Sourcepub fn as_mut_ptr(&mut self) -> *mut c_void
pub fn as_mut_ptr(&mut self) -> *mut c_void
Unique mutable base pointer. Requires &mut self so the borrow checker
forbids two writers sharing one buffer — this is what makes the Sync
impl sound (a shared &DeviceBuffer can never hand out a writable
pointer through safe code).
Sourcepub fn into_raw(self) -> *mut c_void
pub fn into_raw(self) -> *mut c_void
Consume the handle, returning the raw pointer without freeing it. The
caller assumes the single-free obligation from DeviceBuffer::from_raw_parts.