diff --git a/talc/src/span.rs b/talc/src/span.rs index 5a66db0..17c3cd2 100644 --- a/talc/src/span.rs +++ b/talc/src/span.rs @@ -1,4 +1,8 @@ -use core::ops::Range; +use core::{ + hash::{Hash, Hasher}, + ops::Range, + ptr::null_mut, +}; use crate::ptr_utils::*; @@ -11,7 +15,7 @@ use crate::ptr_utils::*; /// the specific values of `base` and `acme` are considered meaningless. /// * Empty spans contain nothing and overlap with nothing. /// * Empty spans are contained by any sized span. -#[derive(Clone, Copy, Hash)] +#[derive(Clone, Copy)] pub struct Span { base: *mut u8, acme: *mut u8, @@ -120,11 +124,24 @@ impl From<*const [T; N]> for Span { impl PartialEq for Span { fn eq(&self, other: &Self) -> bool { - self.is_empty() && other.is_empty() || self.base == other.base && self.acme == other.acme + self.is_empty() && other.is_empty() + || core::ptr::eq(self.base, other.base) && core::ptr::eq(self.acme, other.acme) } } impl Eq for Span {} +impl Hash for Span { + fn hash(&self, hasher: &mut H) { + if self.is_empty() { + null_mut::().hash(hasher); + null_mut::().hash(hasher); + } else { + self.base.hash(hasher); + self.acme.hash(hasher); + } + } +} + impl Span { /// Returns whether `base >= acme`. #[inline] diff --git a/talc/src/talc.rs b/talc/src/talc.rs index 1770217..a2d2021 100644 --- a/talc/src/talc.rs +++ b/talc/src/talc.rs @@ -322,9 +322,31 @@ impl Talc { } /// Allocate a contiguous region of memory according to `layout`, if possible. + /// If the allocation is not currently possible, attempt to recover via the + /// specified [`OomHandler`]. + /// See [`Self::malloc_without_oom_handler`] for allocating without automatic OOM recovery. + /// /// # Safety /// `layout.size()` must be nonzero. pub unsafe fn malloc(&mut self, layout: Layout) -> Result, ()> { + self.malloc_impl(layout, true) + } + + /// Allocate a contiguous region of memory according to `layout`, if possible. + /// If the allocation is not currently possible, do not attempt to recover via + /// the specified [`OomHandler`] and always return `Err(())`. + /// + /// # Safety + /// `layout.size()` must be nonzero. + pub unsafe fn malloc_without_oom_handler(&mut self, layout: Layout) -> Result, ()> { + self.malloc_impl(layout, false) + } + + unsafe fn malloc_impl( + &mut self, + layout: Layout, + handle_oom: bool, + ) -> Result, ()> { debug_assert!(layout.size() != 0); self.scan_for_errors(); @@ -332,7 +354,13 @@ impl Talc { // this returns None if there are no heaps or allocatable memory match self.get_sufficient_chunk(layout) { Some(payload) => break payload, - None => _ = O::handle_oom(self, layout)?, + None => { + if handle_oom { + _ = O::handle_oom(self, layout)? + } else { + return Err(()); + } + } } };