@@ -79,6 +79,8 @@ are tagged with attributes:
79
79
/// Behavior is undefined if the requested size is 0 or the alignment is not a
80
80
/// power of 2. The alignment must be no larger than the largest supported page
81
81
/// size on the platform.
82
+ ///
83
+ /// This function is required.
82
84
#[allocator(allocate)]
83
85
pub fn allocate (size : usize , align : usize ) -> * mut u8 {
84
86
...
@@ -92,6 +94,9 @@ pub fn allocate(size: usize, align: usize) -> *mut u8 {
92
94
/// Behavior is undefined if the requested size is 0 or the alignment is not a
93
95
/// power of 2. The alignment must be no larger than the largest supported page
94
96
/// size on the platform.
97
+ ///
98
+ /// This function is optional. If not provided, `allocate` will be called and
99
+ /// the resulting buffer will be zerored.
95
100
#[allocator(allocate_zeroed)]
96
101
pub fn allocate_zeroed (size : usize , align : usize ) -> * mut u8 {
97
102
...
@@ -103,6 +108,8 @@ pub fn allocate_zeroed(size: usize, align: usize) -> *mut u8 {
103
108
///
104
109
/// The `old_size` and `align` parameters are the parameters that were used to
105
110
/// create the allocation referenced by `ptr`.
111
+ ///
112
+ /// This function is required.
106
113
#[allocator(deallocate)]
107
114
pub fn deallocate (ptr : * mut u8 , old_size : usize , align : usize ) {
108
115
...
@@ -122,6 +129,11 @@ pub fn deallocate(ptr: *mut u8, old_size: usize, align: usize) {
122
129
///
123
130
/// The `old_size` and `align` parameters are the parameters that were used to
124
131
/// create the allocation referenced by `ptr`.
132
+ ///
133
+ /// This function is optional. If not provided, an implementation will be
134
+ /// generated which calls `allocate` to obtain a new buffer, copies the old
135
+ /// memory contents to the new buffer, and then calls `deallocate` on the old
136
+ /// buffer.
125
137
#[allocator(reallocate)]
126
138
pub fn reallocate (ptr : * mut u8 , old_size : usize , size : usize , align : usize ) -> * mut u8 {
127
139
...
@@ -155,9 +167,9 @@ The allocator functions must be publicly accessible, but can have any name and
155
167
be defined in any module. However, it is recommended to use the names above in
156
168
the crate root to minimize confusion.
157
169
158
- An allocator must provide all functions with the exception of
159
- ` reallocate_inplace ` . New functions can be added to the API in the future in a
160
- similar way to ` reallocate_inplace ` .
170
+ Note that new functions can be added to this API in the future as long as they
171
+ can have default implementations in a similar manner to other optional
172
+ functions .
161
173
162
174
## Using an allocator
163
175
@@ -240,9 +252,47 @@ The allocator APIs could be simplified to a more "traditional"
240
252
malloc/calloc/free API at the cost of an efficiency loss when using allocators
241
253
with more powerful APIs.
242
254
255
+ The global allocator could be an instance of the ` Allocator ` trait. Since that
256
+ trait's methods take ` &mut self ` , things are a bit complicated however. The
257
+ allocator would most likely need to be a ` const ` type implementing ` Allocator `
258
+ since it wouldn't be sound to interact with a static. This may cause confusion
259
+ since the allocator itself will therefor not be allowed to maintain any state
260
+ internally since a new instance will be created for each use. In addition, the
261
+ ` Allocator ` trait uses a ` Layout ` type as a higher level encapsulation of the
262
+ requested alignment and size of the allocation. The larger API surface area
263
+ will most likely cause this feature to have a significantly longer stabilization
264
+ period.
265
+
243
266
# Unresolved questions
244
267
[ unresolved ] : #unresolved-questions
245
268
246
269
It is currently forbidden to pass a null pointer to ` deallocate ` , though this is
247
270
guaranteed to be a noop with libc's ` free ` at least. Some kinds of patterns in C
248
271
are cleaner when null pointers can be ` free ` d - is the same true for Rust?
272
+
273
+ The ` Allocator ` trait defines several methods that do not have corresponding
274
+ implementations here:
275
+
276
+ * ` oom ` , which is called after a failed allocation to provide any allocator
277
+ specific messaging that may exist.
278
+ * ` usable_size ` , which is mentioned above as being unused, and should probably
279
+ be removed from this trait as well.
280
+ * ` alloc_excess ` , which is like ` alloc ` but returns the entire usable size
281
+ including any extra space beyond the requested size.
282
+ * Some other higher level convenience methods like ` alloc_array ` .
283
+
284
+ Should any of these be added to the global allocator as well? It may make sense
285
+ to add ` alloc_excess ` to the allocator API. This can either have a default
286
+ implementation which simply calls ` allocate ` and returns the input size, or
287
+ calls ` allocate ` followed by ` reallocate_inplace ` .
288
+
289
+ The existing ` usable_size ` function (proposed for removal) only takes a size and
290
+ align. A similar, but potentially more useful API is one that takes a pointer
291
+ to a heap allocated region and returns the usable size of it. This is supported
292
+ as a GNU extension ` malloc_useable_size ` in the system allocator, and in
293
+ jemalloc as well. An [ issue] [ usable_size ] has been filed to add this to support
294
+ this to aid heap usage diagnostic crates. It would presumably have to return an
295
+ ` Option ` to for allocators that do not have such a function, but this limits
296
+ its usefulness if support can't be guaranteed.
297
+
298
+ [ usable_size ] : https://github.com/rust-lang/rust/issues/32075
0 commit comments