Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions talc/src/span.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use core::ops::Range;
use core::{
hash::{Hash, Hasher},
ops::Range,
ptr::null_mut,
};

use crate::ptr_utils::*;

Expand All @@ -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,
Expand Down Expand Up @@ -120,11 +124,24 @@ impl<T, const N: usize> 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<H: Hasher>(&self, hasher: &mut H) {
if self.is_empty() {
null_mut::<u8>().hash(hasher);
null_mut::<u8>().hash(hasher);
} else {
self.base.hash(hasher);
self.acme.hash(hasher);
}
}
}

impl Span {
/// Returns whether `base >= acme`.
#[inline]
Expand Down
30 changes: 29 additions & 1 deletion talc/src/talc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,17 +322,45 @@ impl<O: OomHandler> Talc<O> {
}

/// 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<NonNull<u8>, ()> {
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<NonNull<u8>, ()> {
self.malloc_impl(layout, false)
}

unsafe fn malloc_impl(
&mut self,
layout: Layout,
handle_oom: bool,
) -> Result<NonNull<u8>, ()> {
debug_assert!(layout.size() != 0);
self.scan_for_errors();

let (mut free_base, free_acme, alloc_base) = loop {
// 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(());
}
}
}
};

Expand Down