@@ -73,9 +73,39 @@ trait described in [RFC 1398][], but is stripped down and the methods take
73
73
[ RFC 1398 ] : https://github.com/rust-lang/rfcs/blob/master/text/1398-kinds-of-allocators.md
74
74
75
75
``` rust
76
-
76
+ /// A trait implemented by objects that can be global allocators.
77
+ ///
78
+ /// Instances of this trait can be used to back allocations done through the
79
+ /// `std::heap` API. This trait represents the fundamental ability to allocate
80
+ /// memory in Rust.
81
+ ///
82
+ /// To use a global allocator you'll need to use the `#[global_allocator]`
83
+ /// attribute like so:
84
+ ///
85
+ /// ```
86
+ /// extern crate my_allocator;
87
+ ///
88
+ /// #[global_allocator]
89
+ /// static ALLOCATOR: MyAllocator = my_allocator::INIT;
90
+ ///
91
+ /// fn main() {
92
+ /// let _b = Box::new(2); // uses `MyAllocator` above
93
+ /// }
94
+ /// ```
95
+ ///
96
+ /// # Unsafety
97
+ ///
98
+ /// This trait is an `unsafe` trait as there are a number of guarantees a global
99
+ /// allocator must adhere to which aren't expressible through the type system.
100
+ /// First and foremost types that implement this trait must behave like, well,
101
+ /// allocators! All pointers returned from `allocate` that are active in a
102
+ /// program (disregarding those `deallocate`d) must point to disjoint chunks of
103
+ /// memory. In other words, allocations need to be distinct and can't overlap.
104
+ ///
105
+ /// Additionally it must be safe to allocate a chunk of memory on any thread of
106
+ /// a program and then deallocate it on any other thread of the program.
77
107
#[lang = " global_allocator" ]
78
- pub unsafe trait GlobalAllocator : Send + Sync {
108
+ pub unsafe trait GlobalAllocator : Send + Sync + ' static {
79
109
/// Returns a pointer to a newly allocated region of memory suitable for the
80
110
/// provided `Layout`. The contents of the memory are undefined.
81
111
///
@@ -110,7 +140,7 @@ pub unsafe trait GlobalAllocator: Send + Sync {
110
140
///
111
141
/// The pointer must correspond to a region of memory previously allocated
112
142
/// by this allocator with the provided layout.
113
- pub fn reallocate (& self , ptr : * mut u8 , old_layout : Layout , layout : Layout ) -> * mut u8 {
143
+ pub unsafe fn reallocate (& self , ptr : * mut u8 , old_layout : Layout , layout : Layout ) -> * mut u8 {
114
144
let new_ptr = self . alloc (layout );
115
145
if ! new_ptr . is_null () {
116
146
ptr :: copy_nonoverlapping (ptr , new_ptr , cmp :: min (old_layout . size (), layout . size ()));
@@ -128,6 +158,12 @@ trait: `usable_size` which is used nowhere in the standard library, and
128
158
A global allocator is a type implementing ` GlobalAllocator ` which can be
129
159
constructed in a constant expression.
130
160
161
+ Note that the precise type signatures used here are a little up for debate. It's
162
+ expected that they will be settled (along with accompanying documentation as to
163
+ guarantees) as part of stabilization in [ rust-lang/rust #27700 ] [ stab-issue ] .
164
+
165
+ [ stab-issue ] : https://github.com/rust-lang/rust/issues/27700
166
+
131
167
## Using an allocator
132
168
133
169
While the ` GlobalAllocator ` trait can be used like any other, the most common
@@ -148,21 +184,21 @@ pub unsafe fn deallocate(&self, ptr: *mut u8, layout: Layout) {
148
184
...
149
185
}
150
186
151
- pub fn reallocate (ptr : * mut u8 , old_layout : Layout , layout : Layout ) -> * mut u8 {
187
+ pub unsafe fn reallocate (ptr : * mut u8 , old_layout : Layout , layout : Layout ) -> * mut u8 {
152
188
...
153
189
}
154
190
```
155
191
156
192
Each of these functions simply delegates to the selected global allocator. The
157
193
allocator is selected by tagging a static value of a type implementing
158
- ` GlobalAllocator ` with the ` #[allocator ] ` annotation:
194
+ ` GlobalAllocator ` with the ` #[global_allocator ] ` annotation:
159
195
160
196
``` rust
161
197
extern crate my_allocator;
162
198
163
199
use my_allocator :: {MyAllocator , MY_ALLOCATOR_INIT };
164
200
165
- #[allocator ]
201
+ #[global_allocator ]
166
202
static ALLOCATOR : MyAllocator = MY_ALLOCATOR_INIT ;
167
203
168
204
fn main () {
@@ -175,23 +211,60 @@ other static would bed.
175
211
176
212
## Standard library
177
213
178
- A small ` alloc_api ` crate will be created which will contain the ` Layout ` type.
179
- The initial API will be more conservative than that described in [ RFC 1398] [ ] ,
180
- possibly nothing more than a ` from_size_align ` constructor and accessors for
181
- ` size ` and ` align ` .
214
+ A ` core::heap ` module will be added with the ` Layout ` type and the
215
+ ` GlobalAllocator ` trait. The initial API of ` Layout ` will be more conservative
216
+ than that described in [ RFC 1398] [ ] , possibly nothing more than a
217
+ ` from_size_align ` constructor and accessors for ` size ` and ` align ` . It is
218
+ intended that the API will grow over time with conveniences such as
219
+ ` Layout::new::<T>() ` .
220
+
221
+ The ` alloc::heap ` module will reexport these types from ` core::heap ` . It will
222
+ also provide top-level functions (like ` allocate ` above) which do not take an
223
+ allocator but instead are routed through the global allocator. The ` alloc `
224
+ crate, however, will not provide a global allocator. Instead the compiler will
225
+ understand that crates which transitively depend on ` alloc ` will require an
226
+ allocator, with a per-target fallback default allocator used by the compiler.
182
227
183
- The standard library will gain a new stable crate - ` alloc_system ` . This is the
184
- default allocator crate and corresponds to the "system" allocator (i.e. ` malloc `
185
- etc on Unix and ` HeapAlloc ` etc on Windows).
228
+ The standard library will grow a ` std::heap ` module that reexports the contents
229
+ of ` alloc::heap ` . Additionally it will contain a system allocator definition:
186
230
187
- The ` alloc::heap ` module will be reexported in ` std ` and stabilized. It will
188
- simply contain functions matching directly to those defined by the allocator
189
- API. The ` alloc ` crate itself may also be stabilized at a later date, but this
190
- RFC does not propose that. ` Layout ` will be reexported in the ` heap ` module.
231
+ ``` rust
232
+ pub struct SystemAllocator ;
233
+
234
+ impl GlobalAllocator for SystemAllocator {
235
+ // ...
236
+ }
237
+ ```
238
+
239
+ The ` SystemAllocator ` is defined as having zero size, no fields, and always
240
+ referring to the OS allocator (i.e. ` malloc ` etc on Unix and ` HeapAlloc ` etc on
241
+ Windows).
242
+
243
+ The existing ` alloc_system ` and ` alloc_jemalloc ` crates will likely be
244
+ deprecated and eventually removed. The ` alloc_system ` crate is replaced with the
245
+ ` SystemAllocator ` structure in the standard library and the ` alloc_jemalloc `
246
+ crate will become available on crates.io. The ` alloc_jemalloc ` crate will likely
247
+ look like:
248
+
249
+ ``` rust
250
+ pub struct Jemalloc ;
251
+
252
+ impl GlobalAllocator for Jemalloc {
253
+ // ...
254
+ }
255
+ ```
191
256
192
- The existing ` alloc_jemalloc ` may continue to exist as an implementation detail
193
- of the Rust compiler, but it will never be stabilized. Applications wishing to
194
- use jemalloc can use a third-party crate from crates.io.
257
+ It is not proposed in this RFC to switch the per-platform default allocator just
258
+ yet. Assuming everything goes smoothly, however, it will likely be defined as
259
+ ` SystemAllocator ` as platforms transition away from jemalloc-by-default once the
260
+ jemalloc-from-crates.io is stable and usable.
261
+
262
+ The compiler will also no longer forbid cyclic the cyclic dependency between a
263
+ crate defining an implementation of an allocator and the ` alloc ` crate itself.
264
+ As a vestige of the current implementation this is only to get around linkage
265
+ errors where the liballoc rlib references symbols defined in the "allocator
266
+ crate". With this RFC the compiler has far more control over the ABI and linkage
267
+ here, so this restriction is no longer necessary.
195
268
196
269
# How We Teach This
197
270
[ how-we-teach-this ] : #how-we-teach-this
0 commit comments