Skip to content

Commit

Permalink
Rollup merge of rust-lang#81864 - ijackson:globalalloc-example, r=Ama…
Browse files Browse the repository at this point in the history
…nieu

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 rust-lang#81847
  • Loading branch information
Dylan-DPC authored Jul 21, 2021
2 parents b41936b + 07e11e8 commit 9a888ea
Showing 1 changed file with 56 additions and 11 deletions.
67 changes: 56 additions & 11 deletions library/core/src/alloc/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,69 @@ use crate::ptr;
///
/// # 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),
/// };
///
/// fn main() {
/// unsafe {
/// assert!(alloc(Layout::new::<u32>()).is_null())
/// 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() {
/// let _s = format!("allocating a string!");
/// let currently = ALLOCATOR.remaining.load(Acquire);
/// println!("allocated so far: {}", ARENA_SIZE - currently);
/// }
/// ```
///
Expand Down

0 comments on commit 9a888ea

Please sign in to comment.