docs: GlobalAlloc: completely replace example with one that works
Since this is an example, this could really do with some review from someone familiar with unsafe stuff ! I made the example no longer `no_run` since it works for me. Fixes #81847 Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk> Co-authored-by: Amanieu d'Antras <amanieu@gmail.com>
This commit is contained in:
parent
8df945c471
commit
07e11e8495
@ -20,24 +20,69 @@
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::alloc::{GlobalAlloc, Layout, alloc};
|
||||
/// ```
|
||||
/// use std::alloc::{GlobalAlloc, Layout};
|
||||
/// use std::cell::UnsafeCell;
|
||||
/// use std::ptr::null_mut;
|
||||
/// use std::sync::atomic::{
|
||||
/// AtomicUsize,
|
||||
/// Ordering::{Acquire, SeqCst},
|
||||
/// };
|
||||
///
|
||||
/// struct MyAllocator;
|
||||
///
|
||||
/// unsafe impl GlobalAlloc for MyAllocator {
|
||||
/// unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { null_mut() }
|
||||
/// unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
|
||||
/// const ARENA_SIZE: usize = 128 * 1024;
|
||||
/// #[repr(C, align(131072))] // 131072 == ARENA_SIZE.
|
||||
/// struct SimpleAllocator {
|
||||
/// arena: UnsafeCell<[u8; ARENA_SIZE]>,
|
||||
/// remaining: AtomicUsize, // we allocate from the top, counting down
|
||||
/// }
|
||||
///
|
||||
/// #[global_allocator]
|
||||
/// static A: MyAllocator = MyAllocator;
|
||||
/// static ALLOCATOR: SimpleAllocator = SimpleAllocator {
|
||||
/// arena: UnsafeCell::new([0x55; ARENA_SIZE]),
|
||||
/// remaining: AtomicUsize::new(ARENA_SIZE),
|
||||
/// };
|
||||
///
|
||||
/// unsafe impl Sync for SimpleAllocator {}
|
||||
///
|
||||
/// unsafe impl GlobalAlloc for SimpleAllocator {
|
||||
/// unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||
/// let size = layout.size();
|
||||
/// let align = layout.align();
|
||||
///
|
||||
/// // `Layout` contract forbids making a `Layout` with align=0, or align not power of 2.
|
||||
/// // So we can safely use a mask to ensure alignment without worrying about UB.
|
||||
/// let align_mask_to_round_down = !(align - 1);
|
||||
///
|
||||
/// if align > ARENA_SIZE {
|
||||
/// // align may be > size !
|
||||
/// return null_mut();
|
||||
/// }
|
||||
///
|
||||
/// let mut allocated = 0;
|
||||
/// if self
|
||||
/// .remaining
|
||||
/// .fetch_update(SeqCst, SeqCst, |mut remaining| {
|
||||
/// if size > remaining {
|
||||
/// return None;
|
||||
/// }
|
||||
/// remaining -= size;
|
||||
/// remaining &= align_mask_to_round_down;
|
||||
/// allocated = remaining;
|
||||
/// Some(remaining)
|
||||
/// })
|
||||
/// .is_err()
|
||||
/// {
|
||||
/// return null_mut();
|
||||
/// };
|
||||
/// (self.arena.get() as *mut u8).add(allocated)
|
||||
/// }
|
||||
/// unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// unsafe {
|
||||
/// assert!(alloc(Layout::new::<u32>()).is_null())
|
||||
/// }
|
||||
/// let _s = format!("allocating a string!");
|
||||
/// let currently = ALLOCATOR.remaining.load(Acquire);
|
||||
/// println!("allocated so far: {}", ARENA_SIZE - currently);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
|
Loading…
Reference in New Issue
Block a user