pub mod header_store;
pub mod manager;
pub mod static_manager;
#[cfg(feature = "alloc")]
pub mod heap_manager;
#[cfg(feature = "std")]
pub mod concurrent_manager;
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum MemoryClass {
Host,
PinnedHost,
Device(u8),
Shared,
}
#[allow(clippy::derivable_impls)]
impl Default for MemoryClass {
fn default() -> Self {
MemoryClass::Host
}
}
const HOST_BIT: u32 = 0;
const PINNED_HOST_BIT: u32 = 1;
const DEVICE_BASE_BIT: u32 = 2;
const DEVICE_MAX_ORDINAL: u8 = 15; const SHARED_BIT: u32 = 18;
const fn device_bit(ordinal: u8) -> u32 {
DEVICE_BASE_BIT + ordinal as u32
}
const DEVICE_MASK: u32 = {
((1u32 << ((DEVICE_MAX_ORDINAL as u32) + 1)) - 1) << DEVICE_BASE_BIT
};
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PlacementAcceptance {
bits: u32,
}
impl Default for PlacementAcceptance {
fn default() -> Self {
Self::empty().with_host()
}
}
impl PlacementAcceptance {
#[inline]
pub const fn empty() -> Self {
Self { bits: 0 }
}
#[inline]
pub const fn from_bits(bits: u32) -> Self {
Self { bits }
}
#[inline]
pub const fn bits(&self) -> &u32 {
&self.bits
}
#[inline]
pub const fn is_empty(&self) -> bool {
self.bits == 0
}
#[inline]
pub const fn union(self, other: Self) -> Self {
Self {
bits: self.bits | other.bits,
}
}
#[inline]
pub const fn intersect(self, other: Self) -> Self {
Self {
bits: self.bits & other.bits,
}
}
#[inline]
pub const fn contains(self, other: Self) -> bool {
(self.bits & other.bits) == other.bits
}
#[inline]
pub const fn host_all() -> Self {
Self::empty().with_host().with_pinned_host()
}
#[inline]
pub const fn with_host(mut self) -> Self {
self.bits |= 1 << HOST_BIT;
self
}
#[inline]
pub const fn with_pinned_host(mut self) -> Self {
self.bits |= 1 << PINNED_HOST_BIT;
self
}
#[inline]
pub const fn with_device(mut self, ordinal: u8) -> Self {
let o = (ordinal & DEVICE_MAX_ORDINAL) as u32;
self.bits |= 1 << (DEVICE_BASE_BIT + o);
self
}
#[inline]
pub const fn try_with_device(self, ordinal: u8) -> Option<Self> {
if ordinal <= DEVICE_MAX_ORDINAL {
Some(self.with_device(ordinal))
} else {
None
}
}
#[inline]
pub const fn with_all_devices(mut self) -> Self {
self.bits |= DEVICE_MASK;
self
}
#[inline]
pub const fn with_shared(mut self) -> Self {
self.bits |= 1 << SHARED_BIT;
self
}
#[inline]
pub const fn accepts(&self, class: MemoryClass) -> bool {
match class {
MemoryClass::Host => (self.bits & (1 << HOST_BIT)) != 0,
MemoryClass::PinnedHost => (self.bits & (1 << PINNED_HOST_BIT)) != 0,
MemoryClass::Device(o) => {
let o = (o & DEVICE_MAX_ORDINAL) as u32;
(self.bits & (1 << device_bit(o as u8))) != 0
}
MemoryClass::Shared => (self.bits & (1 << SHARED_BIT)) != 0,
}
}
#[inline]
pub const fn exactly(class: MemoryClass) -> Self {
match class {
MemoryClass::Host => Self::empty().with_host(),
MemoryClass::PinnedHost => Self::empty().with_pinned_host(),
MemoryClass::Device(o) => Self::empty().with_device(o),
MemoryClass::Shared => Self::empty().with_shared(),
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct BufferDescriptor {
bytes: usize,
}
impl BufferDescriptor {
#[inline]
pub const fn new(bytes: usize) -> Self {
Self { bytes }
}
#[inline]
pub const fn bytes(&self) -> &usize {
&self.bytes
}
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PlacementDecision {
ZeroCopy,
AdaptRequired,
}
#[inline]
pub const fn decide_placement(
acceptance: PlacementAcceptance,
current: MemoryClass,
) -> PlacementDecision {
if acceptance.accepts(current) {
PlacementDecision::ZeroCopy
} else {
PlacementDecision::AdaptRequired
}
}