loom/alloc.rs
1//! Memory allocation APIs
2
3use crate::rt;
4
5#[doc(no_inline)]
6pub use std::alloc::Layout;
7
8/// Allocate memory with the global allocator.
9///
10/// This is equivalent to the standard library's [`std::alloc::alloc`], but with
11/// the addition of leak tracking for allocated objects. Loom's leak tracking
12/// will not function for allocations not performed via this method.
13///
14/// This function forwards calls to the [`GlobalAlloc::alloc`] method
15/// of the allocator registered with the `#[global_allocator]` attribute
16/// if there is one, or the `std` crate’s default.
17///
18/// # Safety
19///
20/// See [`GlobalAlloc::alloc`].
21///
22/// [`GlobalAlloc::alloc`]: std::alloc::GlobalAlloc::alloc
23#[track_caller]
24pub unsafe fn alloc(layout: Layout) -> *mut u8 {
25 let ptr = std::alloc::alloc(layout);
26 rt::alloc(ptr, location!());
27 ptr
28}
29
30/// Allocate zero-initialized memory with the global allocator.
31///
32/// This is equivalent to the standard library's [`std::alloc::alloc_zeroed`],
33/// but with the addition of leak tracking for allocated objects. Loom's leak
34/// tracking will not function for allocations not performed via this method.
35///
36/// This function forwards calls to the [`GlobalAlloc::alloc_zeroed`] method
37/// of the allocator registered with the `#[global_allocator]` attribute
38/// if there is one, or the `std` crate’s default.
39///
40/// # Safety
41///
42/// See [`GlobalAlloc::alloc_zeroed`].
43///
44/// [`GlobalAlloc::alloc_zeroed`]: std::alloc::GlobalAlloc::alloc_zeroed
45#[track_caller]
46pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
47 let ptr = std::alloc::alloc_zeroed(layout);
48 rt::alloc(ptr, location!());
49 ptr
50}
51
52/// Deallocate memory with the global allocator.
53///
54/// This is equivalent to the standard library's [`std::alloc::dealloc`],
55/// but with the addition of leak tracking for allocated objects. Loom's leak
56/// tracking may report false positives if allocations allocated with
57/// [`loom::alloc::alloc`] or [`loom::alloc::alloc_zeroed`] are deallocated via
58/// [`std::alloc::dealloc`] rather than by this function.
59///
60/// This function forwards calls to the [`GlobalAlloc::dealloc`] method
61/// of the allocator registered with the `#[global_allocator]` attribute
62/// if there is one, or the `std` crate’s default.
63///
64/// # Safety
65///
66/// See [`GlobalAlloc::dealloc`].
67///
68/// [`GlobalAlloc::dealloc`]: std::alloc::GlobalAlloc::dealloc
69/// [`loom::alloc::alloc`]: crate::alloc::alloc
70/// [`loom::alloc::alloc_zeroed`]: crate::alloc::alloc_zeroed
71#[track_caller]
72pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
73 rt::dealloc(ptr, location!());
74 std::alloc::dealloc(ptr, layout)
75}
76
77/// Track allocations, detecting leaks
78#[derive(Debug)]
79pub struct Track<T> {
80 value: T,
81 /// Drop guard tracking the allocation's lifetime.
82 _obj: rt::Allocation,
83}
84
85impl<T> Track<T> {
86 /// Track a value for leaks
87 #[track_caller]
88 pub fn new(value: T) -> Track<T> {
89 Track {
90 value,
91 _obj: rt::Allocation::new(location!()),
92 }
93 }
94
95 /// Get a reference to the value
96 pub fn get_ref(&self) -> &T {
97 &self.value
98 }
99
100 /// Get a mutable reference to the value
101 pub fn get_mut(&mut self) -> &mut T {
102 &mut self.value
103 }
104
105 /// Stop tracking the value for leaks
106 pub fn into_inner(self) -> T {
107 self.value
108 }
109}