Skip to main content

DeviceBuffer

Struct DeviceBuffer 

Source
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 DeviceBuffer without passing it to deallocate leaks 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 allocate with exactly one deallocate. Higher layers may wrap this handle in an RAII/Arc type 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

Source

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:

  • ptr is non-null and points to the start of an allocation of at least size bytes on device, aligned to at least align bytes.
  • The allocation was produced by device’s EP and will be freed exactly once, only by returning this handle to that EP’s deallocate (or via an equivalent raw free of the pointer obtained from DeviceBuffer::into_raw).
  • No other live DeviceBuffer aliases the same allocation.

align must be a power of two (checked in debug builds).

Source

pub fn device(&self) -> DeviceId

The device this allocation lives on (and whose EP must free it).

Source

pub fn len(&self) -> usize

Allocation size in bytes.

Source

pub fn is_empty(&self) -> bool

Whether the allocation is zero-length.

Source

pub fn alignment(&self) -> usize

Alignment (bytes) the base pointer was allocated to.

Source

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.

Source

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).

Source

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.

Trait Implementations§

Source§

impl Debug for DeviceBuffer

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Send for DeviceBuffer

Source§

impl Sync for DeviceBuffer

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.