Skip to content

Commit 5701178

Browse files
committed
Add AbortAdapter allocator adapter
See its documentation for why its useful
1 parent 68bd5f0 commit 5701178

File tree

2 files changed

+118
-0
lines changed

2 files changed

+118
-0
lines changed

src/liballoc/abort_adapter.rs

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

src/liballoc/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@
123123
#![feature(inclusive_range_methods)]
124124
#![feature(rustc_const_unstable)]
125125
#![feature(const_vec_new)]
126+
#![feature(never_type)]
127+
#![feature(crate_in_paths)]
126128

127129
#![cfg_attr(not(test), feature(fn_traits, i128))]
128130
#![cfg_attr(test, feature(test))]
@@ -144,6 +146,7 @@ mod macros;
144146
// Heaps provided for low-level allocation strategies
145147

146148
pub mod alloc;
149+
pub mod abort_adapter;
147150

148151
#[unstable(feature = "futures_api",
149152
reason = "futures in libcore are unstable",

0 commit comments

Comments
 (0)