pub struct BufferHandle { /* private fields */ }Expand description
A declaration of a buffer’s size, alignment, device location, and sync mode.
A BufferHandle is the in-memory representation of the 16-byte buffer
handle entry in the tensor descriptor’s buffer table (see
docs/spec/metadata.md § Buffer Table). It carries the metadata needed to
locate and access a buffer but does not itself hold a pointer — the actual
memory address is communicated out-of-band via the interchange protocol or
the C ABI (see docs/impl/c-ffi.md).
§Wire layout (ADR-018 § 3, ADR-020)
| Offset | Field | Type | Size |
|---|---|---|---|
| 0 | byte_size | uint64 LE | 8 |
| 8 | alignment | uint32 LE | 4 |
| 12 | device_tag | uint8 | 1 |
| 13 | sync_mode | uint8 | 1 |
| 14 | memory_class | uint8 | 1 |
| 15 | _reserved | uint8 | 1 |
§Alignment rules
alignmentMUST be a power of two.- For non-empty buffers (
byte_size > 0):alignmentMUST be at leastMIN_BUFFER_ALIGNMENT(64 bytes). - For empty buffers (
byte_size == 0): any power-of-two alignment is valid, including1. A reader MUST NOT dereference the pointer of an empty buffer.
See docs/spec/buffer-protocol.md § Alignment for the normative rules.
§Examples
use hurray_core::{BufferHandle, DeviceTag, MemoryClass, SyncMode, MIN_BUFFER_ALIGNMENT};
// Non-empty CPU buffer, minimum SIMD alignment, default Standard class.
let handle = BufferHandle::new(1024, MIN_BUFFER_ALIGNMENT, DeviceTag::Cpu, SyncMode::ProducerSynced).unwrap();
assert_eq!(handle.byte_size(), 1024);
assert_eq!(handle.alignment(), 64);
assert_eq!(handle.device_tag(), DeviceTag::Cpu);
assert_eq!(handle.sync_mode(), SyncMode::ProducerSynced);
assert_eq!(handle.memory_class(), MemoryClass::Standard);
assert!(!handle.is_empty());
// CUDA buffer with Unified memory class.
let unified = BufferHandle::with_memory_class(
4096, 4096, DeviceTag::Cuda, SyncMode::ProducerSynced, MemoryClass::Unified,
).unwrap();
assert_eq!(unified.memory_class(), MemoryClass::Unified);
// Empty buffer — alignment 1 is valid.
let empty = BufferHandle::empty(DeviceTag::Cuda);
assert!(empty.is_empty());
assert_eq!(empty.alignment(), 1);Implementations§
Source§impl BufferHandle
impl BufferHandle
Sourcepub fn new(
byte_size: u64,
alignment: u32,
device_tag: DeviceTag,
sync_mode: SyncMode,
) -> Result<Self>
pub fn new( byte_size: u64, alignment: u32, device_tag: DeviceTag, sync_mode: SyncMode, ) -> Result<Self>
Creates a new BufferHandle with the given size, alignment, device, and sync mode.
§Errors
Error::AlignmentNotPowerOfTwo—alignmentis not a power of two.Error::AlignmentBelowMinimum—byte_size > 0andalignmentis less thanMIN_BUFFER_ALIGNMENT(64).Error::InvalidSyncMode—device_tagisDeviceTag::Cpuandsync_modeis notSyncMode::ProducerSynced(CPU buffers MUST useSYNC_PRODUCER_SYNCEDper the spec).
§Examples
use hurray_core::{BufferHandle, DeviceTag, Error, SyncMode, MIN_BUFFER_ALIGNMENT};
// Valid: non-empty CPU buffer with minimum SIMD alignment.
assert!(BufferHandle::new(512, 64, DeviceTag::Cpu, SyncMode::ProducerSynced).is_ok());
// Valid: CUDA buffer with Event sync.
assert!(BufferHandle::new(512, 64, DeviceTag::Cuda, SyncMode::Event).is_ok());
// Valid: empty buffer with alignment 1.
assert!(BufferHandle::new(0, 1, DeviceTag::Cpu, SyncMode::ProducerSynced).is_ok());
// Error: alignment is not a power of two.
assert!(matches!(
BufferHandle::new(512, 3, DeviceTag::Cpu, SyncMode::ProducerSynced),
Err(Error::AlignmentNotPowerOfTwo { alignment: 3 })
));
// Error: non-empty buffer with alignment below the 64-byte minimum.
assert!(matches!(
BufferHandle::new(512, 32, DeviceTag::Cpu, SyncMode::ProducerSynced),
Err(Error::AlignmentBelowMinimum { alignment: 32, minimum: 64 })
));
// Error: CPU buffer with non-ProducerSynced mode.
assert!(matches!(
BufferHandle::new(512, 64, DeviceTag::Cpu, SyncMode::Event),
Err(Error::InvalidSyncMode(0x01))
));Sourcepub fn with_memory_class(
byte_size: u64,
alignment: u32,
device_tag: DeviceTag,
sync_mode: SyncMode,
memory_class: MemoryClass,
) -> Result<Self>
pub fn with_memory_class( byte_size: u64, alignment: u32, device_tag: DeviceTag, sync_mode: SyncMode, memory_class: MemoryClass, ) -> Result<Self>
Creates a new BufferHandle with an explicit memory class.
Identical to BufferHandle::new but accepts a MemoryClass value.
Use this constructor when the buffer’s memory class is not MemoryClass::Standard
(e.g., CUDA managed memory, Metal shared storage, or peer-to-peer memory).
§Errors
Error::AlignmentNotPowerOfTwo—alignmentis not a power of two.Error::AlignmentBelowMinimum—byte_size > 0andalignment < 64.Error::InvalidSyncMode—device_tagisDeviceTag::Cpuandsync_modeis notSyncMode::ProducerSynced.
§Examples
use hurray_core::{BufferHandle, DeviceTag, MemoryClass, SyncMode};
// CUDA unified (managed) memory buffer.
let handle = BufferHandle::with_memory_class(
4096, 4096, DeviceTag::Cuda, SyncMode::ProducerSynced, MemoryClass::Unified,
).unwrap();
assert_eq!(handle.memory_class(), MemoryClass::Unified);
// CPU host-pinned buffer.
let pinned = BufferHandle::with_memory_class(
512, 64, DeviceTag::Cpu, SyncMode::ProducerSynced, MemoryClass::HostPinned,
).unwrap();
assert_eq!(pinned.memory_class(), MemoryClass::HostPinned);Sourcepub fn empty(device_tag: DeviceTag) -> Self
pub fn empty(device_tag: DeviceTag) -> Self
Creates an empty BufferHandle (zero bytes) on the given device.
The alignment is set to 1 — the minimum valid power-of-two for an
empty buffer — and sync_mode is always SyncMode::ProducerSynced.
This constructor is infallible.
§Examples
use hurray_core::{BufferHandle, DeviceTag, SyncMode};
let handle = BufferHandle::empty(DeviceTag::Cpu);
assert!(handle.is_empty());
assert_eq!(handle.byte_size(), 0);
assert_eq!(handle.alignment(), 1);
assert_eq!(handle.device_tag(), DeviceTag::Cpu);
assert_eq!(handle.sync_mode(), SyncMode::ProducerSynced);Sourcepub fn byte_size(self) -> u64
pub fn byte_size(self) -> u64
Returns the size of the buffer in bytes.
A value of 0 denotes an empty buffer whose backing pointer MUST NOT
be dereferenced.
§Examples
use hurray_core::{BufferHandle, DeviceTag, SyncMode};
let handle = BufferHandle::new(4096, 4096, DeviceTag::Cuda, SyncMode::Event).unwrap();
assert_eq!(handle.byte_size(), 4096);Sourcepub fn alignment(self) -> u32
pub fn alignment(self) -> u32
Returns the minimum alignment of the buffer’s base address in bytes.
Always a power of two. For non-empty buffers, always at least
MIN_BUFFER_ALIGNMENT.
§Examples
use hurray_core::{BufferHandle, DeviceTag, SyncMode, PAGE_ALIGNMENT};
let handle = BufferHandle::new(8192, PAGE_ALIGNMENT, DeviceTag::Cuda, SyncMode::Event).unwrap();
assert_eq!(handle.alignment(), 4096);Sourcepub fn device_tag(self) -> DeviceTag
pub fn device_tag(self) -> DeviceTag
Sourcepub fn sync_mode(self) -> SyncMode
pub fn sync_mode(self) -> SyncMode
Returns the SyncMode describing the producer–consumer ordering guarantee
for this buffer.
§Examples
use hurray_core::{BufferHandle, DeviceTag, SyncMode};
let handle = BufferHandle::new(1024, 64, DeviceTag::Cuda, SyncMode::ConsumerStream).unwrap();
assert_eq!(handle.sync_mode(), SyncMode::ConsumerStream);
// CPU buffers are always ProducerSynced.
let cpu = BufferHandle::new(1024, 64, DeviceTag::Cpu, SyncMode::ProducerSynced).unwrap();
assert_eq!(cpu.sync_mode(), SyncMode::ProducerSynced);Sourcepub fn memory_class(self) -> MemoryClass
pub fn memory_class(self) -> MemoryClass
Returns the MemoryClass describing how this buffer is accessible.
§Examples
use hurray_core::{BufferHandle, DeviceTag, MemoryClass, SyncMode};
// new() defaults to Standard.
let handle = BufferHandle::new(1024, 64, DeviceTag::Cuda, SyncMode::ProducerSynced).unwrap();
assert_eq!(handle.memory_class(), MemoryClass::Standard);
// with_memory_class() sets an explicit class.
let unified = BufferHandle::with_memory_class(
1024, 64, DeviceTag::Cuda, SyncMode::ProducerSynced, MemoryClass::Unified,
).unwrap();
assert_eq!(unified.memory_class(), MemoryClass::Unified);Sourcepub fn is_empty(self) -> bool
pub fn is_empty(self) -> bool
Returns true if this buffer has zero bytes (byte_size == 0).
Readers MUST NOT dereference the pointer of an empty buffer. In C ABI contexts an empty buffer MAY be represented by a null pointer.
§Examples
use hurray_core::{BufferHandle, DeviceTag, SyncMode};
assert!(BufferHandle::empty(DeviceTag::Cpu).is_empty());
assert!(!BufferHandle::new(1, 64, DeviceTag::Cpu, SyncMode::ProducerSynced).unwrap().is_empty());Trait Implementations§
Source§impl Clone for BufferHandle
impl Clone for BufferHandle
Source§fn clone(&self) -> BufferHandle
fn clone(&self) -> BufferHandle
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreimpl Copy for BufferHandle
Source§impl Debug for BufferHandle
impl Debug for BufferHandle
impl Eq for BufferHandle
Source§impl Hash for BufferHandle
impl Hash for BufferHandle
Source§impl PartialEq for BufferHandle
impl PartialEq for BufferHandle
Source§fn eq(&self, other: &BufferHandle) -> bool
fn eq(&self, other: &BufferHandle) -> bool
self and other values to be equal, and is used by ==.