about summary refs log tree commit diff
path: root/src/libstd/alloc.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd/alloc.rs')
-rw-r--r--src/libstd/alloc.rs89
1 files changed, 87 insertions, 2 deletions
diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs
index 1ff342fa7a7..485b2ffe197 100644
--- a/src/libstd/alloc.rs
+++ b/src/libstd/alloc.rs
@@ -73,15 +73,100 @@
 
 use core::sync::atomic::{AtomicPtr, Ordering};
 use core::{mem, ptr};
+use core::ptr::NonNull;
 use sys_common::util::dumb_print;
 
 #[stable(feature = "alloc_module", since = "1.28.0")]
 #[doc(inline)]
 pub use alloc_crate::alloc::*;
 
+/// The default memory allocator provided by the operating system.
+///
+/// This is based on `malloc` on Unix platforms and `HeapAlloc` on Windows,
+/// plus related functions.
+///
+/// This type implements the `GlobalAlloc` trait and Rust programs by deafult
+/// work as if they had this definition:
+///
+/// ```rust
+/// use std::alloc::System;
+///
+/// #[global_allocator]
+/// static A: System = System;
+///
+/// fn main() {
+///     let a = Box::new(4); // Allocates from the system allocator.
+///     println!("{}", a);
+/// }
+/// ```
+///
+/// You can also define your own wrapper around `System` if you'd like, such as
+/// keeping track of the number of all bytes allocated:
+///
+/// ```rust
+/// use std::alloc::{System, GlobalAlloc, Layout};
+/// use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering::SeqCst};
+///
+/// struct Counter;
+///
+/// static ALLOCATED: AtomicUsize = ATOMIC_USIZE_INIT;
+///
+/// unsafe impl GlobalAlloc for Counter {
+///     unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+///         let ret = System.alloc(layout);
+///         if !ret.is_null() {
+///             ALLOCATED.fetch_add(layout.size(), SeqCst);
+///         }
+///         return ret
+///     }
+///
+///     unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
+///         System.dealloc(ptr, layout);
+///         ALLOCATED.fetch_sub(layout.size(), SeqCst);
+///     }
+/// }
+///
+/// #[global_allocator]
+/// static A: Counter = Counter;
+///
+/// fn main() {
+///     println!("allocated bytes before main: {}", ALLOCATED.load(SeqCst));
+/// }
+/// ```
+///
+/// It can also be used directly to allocate memory independently of whatever
+/// global allocator has been selected for a Rust program. For example if a Rust
+/// program opts in to using jemalloc as the global allocator, `System` will
+/// still allocate memory using `malloc` and `HeapAlloc`.
 #[stable(feature = "alloc_system_type", since = "1.28.0")]
-#[doc(inline)]
-pub use alloc_system::System;
+#[derive(Debug, Copy, Clone)]
+pub struct System;
+
+#[unstable(feature = "allocator_api", issue = "32838")]
+unsafe impl Alloc for System {
+    #[inline]
+    unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
+        NonNull::new(GlobalAlloc::alloc(self, layout)).ok_or(AllocErr)
+    }
+
+    #[inline]
+    unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
+        NonNull::new(GlobalAlloc::alloc_zeroed(self, layout)).ok_or(AllocErr)
+    }
+
+    #[inline]
+    unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
+        GlobalAlloc::dealloc(self, ptr.as_ptr(), layout)
+    }
+
+    #[inline]
+    unsafe fn realloc(&mut self,
+                      ptr: NonNull<u8>,
+                      layout: Layout,
+                      new_size: usize) -> Result<NonNull<u8>, AllocErr> {
+        NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size)).ok_or(AllocErr)
+    }
+}
 
 static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());