blob: ece228f4580935ed3d5d00cd338389a0412b62f6 [file] [log] [blame]
// Part of the Crubit project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// #![feature(allocator_api)]
use crate::crubit_cc_std_internal::std_allocator::{cpp_delete, cpp_new};
use core::alloc::AllocError;
use core::alloc::Allocator;
use core::alloc::GlobalAlloc;
use core::alloc::Layout;
use core::ffi::c_void;
use core::ptr::NonNull;
pub struct StdAllocator {}
unsafe impl Allocator for StdAllocator {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
// SAFETY: StdAllocator allows for zero-sized allocations.
let raw_ptr = unsafe { self.alloc(layout) };
let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
Ok(NonNull::slice_from_raw_parts(ptr, layout.size()))
}
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
// SAFETY: Allocator and Dealloc have identical preconditions.
unsafe {
self.dealloc(ptr.as_ptr(), layout);
}
}
// NOTE: Also change the GlobalAlloc impl if you add grow/etc.
}
/// StdAllocator is a global allocator which also accepts zero-sized allocations.
///
/// This allows allocations (even of size 0) in Rust to be mixed with deallocations in C++.
/// (Though, since `Global` will not pass through 0-sized allocations, this is currently of
/// limited use.)
unsafe impl GlobalAlloc for StdAllocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
cpp_new(layout.size(), layout.align()) as *mut u8
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
unsafe {
cpp_delete(ptr as *mut c_void, layout.size(), layout.align());
}
}
}
impl Clone for StdAllocator {
fn clone(&self) -> Self {
Self {}
}
}