Skip to content

Commit 4454093

Browse files
committed
Add AbortAdapter allocator adapter
See its documentation for why its useful
1 parent 53538de commit 4454093

File tree

3 files changed

+117
-3
lines changed

3 files changed

+117
-3
lines changed

src/liballoc/abort_adapter.rs

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
//! An allocator adapter that blows up by calling `handle_alloc_error` on all errors.
2+
//!
3+
//! On one hand, concrete allocator implementations should always be written
4+
//! without panicking on user error and OOM to give users maximum
5+
//! flexibility. On the other hand, code that depends on allocation succeeding
6+
//! should depend on `Alloc<Err=!>` to avoid repetitively handling errors from
7+
//! which it cannot recover.
8+
//!
9+
//! This adapter bridges the gap, effectively allowing `Alloc<Err=!>` to be
10+
//! implemented by any allocator.
11+
12+
#![unstable(feature = "allocator_api",
13+
reason = "the precise API and guarantees it provides may be tweaked \
14+
slightly, especially to possibly take into account the \
15+
types being stored to make room for a future \
16+
tracing garbage collector",
17+
issue = "32838")]
18+
19+
use core::usize;
20+
use core::ptr::NonNull;
21+
22+
use crate::alloc::*;
23+
24+
/// An allocator adapter that blows up by calling `handle_alloc_error` on all errors.
25+
///
26+
/// See the [module-level documentation](../../std/abort_adapter/index.html) for more.
27+
#[derive(Copy, Clone, Debug, Default)]
28+
pub struct AbortAdapter<Alloc>(pub Alloc);
29+
30+
impl<A: AllocHelper> AllocHelper for AbortAdapter<A> {
31+
type Err = !;
32+
}
33+
34+
unsafe impl<A: Alloc> Alloc for AbortAdapter<A> {
35+
unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, Self::Err> {
36+
self.0.alloc(layout).or_else(|_| handle_alloc_error(layout))
37+
}
38+
39+
unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
40+
self.0.dealloc(ptr, layout)
41+
}
42+
43+
fn usable_size(&self, layout: &Layout) -> (usize, usize) {
44+
self.0.usable_size(layout)
45+
}
46+
47+
unsafe fn realloc(&mut self,
48+
ptr: NonNull<u8>,
49+
layout: Layout,
50+
new_size: usize) -> Result<NonNull<u8>, Self::Err> {
51+
self.0.realloc(ptr, layout, new_size).or_else(|_| handle_alloc_error(layout))
52+
}
53+
54+
unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<u8>, Self::Err> {
55+
self.0.alloc_zeroed(layout).or_else(|_| handle_alloc_error(layout))
56+
}
57+
58+
unsafe fn alloc_excess(&mut self, layout: Layout) -> Result<Excess, Self::Err> {
59+
self.0.alloc_excess(layout).or_else(|_| handle_alloc_error(layout))
60+
}
61+
62+
unsafe fn grow_in_place(&mut self,
63+
ptr: NonNull<u8>,
64+
layout: Layout,
65+
new_size: usize) -> Result<(), CannotReallocInPlace> {
66+
self.0.grow_in_place(ptr, layout, new_size)
67+
}
68+
69+
unsafe fn shrink_in_place(&mut self,
70+
ptr: NonNull<u8>,
71+
layout: Layout,
72+
new_size: usize) -> Result<(), CannotReallocInPlace> {
73+
self.0.shrink_in_place(ptr, layout, new_size)
74+
}
75+
76+
fn alloc_one<T>(&mut self) -> Result<NonNull<T>, Self::Err>
77+
where Self: Sized
78+
{
79+
self.0.alloc_one().or_else(|_| handle_alloc_error(Layout::new::<T>()))
80+
}
81+
82+
unsafe fn dealloc_one<T>(&mut self, ptr: NonNull<T>)
83+
where Self: Sized
84+
{
85+
self.0.dealloc_one(ptr)
86+
}
87+
88+
fn alloc_array<T>(&mut self, n: usize) -> Result<NonNull<T>, Self::Err>
89+
where Self: Sized
90+
{
91+
self.0.alloc_array(n).or_else(|_| handle_alloc_error(Layout::new::<T>()))
92+
}
93+
94+
unsafe fn realloc_array<T>(&mut self,
95+
ptr: NonNull<T>,
96+
n_old: usize,
97+
n_new: usize) -> Result<NonNull<T>, Self::Err>
98+
where Self: Sized
99+
{
100+
self.0.realloc_array(ptr, n_old, n_new)
101+
.or_else(|_| handle_alloc_error(Layout::new::<T>()))
102+
}
103+
104+
unsafe fn dealloc_array<T>(&mut self, ptr: NonNull<T>, n: usize) -> Result<(), Self::Err>
105+
where Self: Sized
106+
{
107+
self.0.dealloc_array(ptr, n).or_else(|_| handle_alloc_error(Layout::new::<T>()))
108+
}
109+
}

src/liballoc/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@
112112
#![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_array)]
113113
#![feature(alloc_layout_extra)]
114114
#![feature(try_trait)]
115+
#![feature(never_type)]
115116

116117
// Allow testing this library
117118

@@ -128,6 +129,7 @@ mod macros;
128129
// Heaps provided for low-level allocation strategies
129130

130131
pub mod alloc;
132+
pub mod abort_adapter;
131133

132134
// Primitive types using the heaps above
133135

src/liballoc/raw_vec.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,8 @@ impl<T, A: Alloc<Err = AllocErr>> RawVec<T, A> {
422422
-> Result<usize, CollectionAllocErr> {
423423

424424
// Nothing we can really do about these checks :(
425-
let required_cap = used_cap.checked_add(needed_extra_cap).ok_or(CollectionAllocErr::CapacityOverflow)?;
425+
let required_cap = used_cap.checked_add(needed_extra_cap)
426+
.ok_or(CollectionAllocErr::CapacityOverflow)?;
426427
// Cannot overflow, because `cap <= isize::MAX`, and type of `cap` is `usize`.
427428
let double_cap = self.cap * 2;
428429
// `double_cap` guarantees exponential growth.
@@ -651,10 +652,12 @@ impl<T, A: Alloc<Err = AllocErr>> RawVec<T, A> {
651652

652653
// Nothing we can really do about these checks :(
653654
let new_cap = match strategy {
654-
Exact => used_cap.checked_add(needed_extra_cap).ok_or(CollectionAllocErr::CapacityOverflow)?,
655+
Exact => used_cap.checked_add(needed_extra_cap)
656+
.ok_or(CollectionAllocErr::CapacityOverflow)?,
655657
Amortized => self.amortized_new_size(used_cap, needed_extra_cap)?,
656658
};
657-
let new_layout = Layout::array::<T>(new_cap).map_err(|_| CollectionAllocErr::CapacityOverflow)?;
659+
let new_layout = Layout::array::<T>(new_cap)
660+
.map_err(|_| CollectionAllocErr::CapacityOverflow)?;
658661

659662
alloc_guard(new_layout.size())?;
660663

0 commit comments

Comments
 (0)