Description
As Andrei Alexandrescu discusses in this great talk, in order to make it possible to construct new allocators by composing existing ones, each allocator must support an ownership check.
Consider, for example, a "fallback allocator" - an allocator which operates by wrapping two other allocators, serving allocation requests by trying to allocate from the first allocator and falling back to the second one if the first request fails. In Rust:
fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
if let Ok(ptr) = self.first.alloc(layout.clone()) {
Ok(ptr)
} else {
self.second.alloc(layout)
}
}
In order to service deallocation requests to this allocator, however, you need to be able to detect which allocator a given pointer came from. If we assume an owns
method, this looks like:
fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
if self.first.owns(ptr, layout.clone()) {
self.first.dealloc(ptr, layout);
} else {
self.second.dealloc(ptr, layout);
}
}
As Andrei discusses in that talk, modern allocators are nothing but composition - size classes, different allocation strategies, falling back to mmap
for certain allocations, etc. Thus, I think that it's important that we take composability seriously, and ensure that our Alloc
trait is composable. This requires adding an owns
method. Concretely, I'm suggesting the following signature be added to the Alloc
trait:
fn owns(&self, ptr: *mut u8, layout: Layout) -> bool;