Skip to content

Commit 56d6820

Browse files
committed
Tweaks from feedback
1 parent df69ec1 commit 56d6820

File tree

1 file changed

+53
-3
lines changed

1 file changed

+53
-3
lines changed

text/0000-global-allocators.md

+53-3
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ are tagged with attributes:
7979
/// Behavior is undefined if the requested size is 0 or the alignment is not a
8080
/// power of 2. The alignment must be no larger than the largest supported page
8181
/// size on the platform.
82+
///
83+
/// This function is required.
8284
#[allocator(allocate)]
8385
pub fn allocate(size: usize, align: usize) -> *mut u8 {
8486
...
@@ -92,6 +94,9 @@ pub fn allocate(size: usize, align: usize) -> *mut u8 {
9294
/// Behavior is undefined if the requested size is 0 or the alignment is not a
9395
/// power of 2. The alignment must be no larger than the largest supported page
9496
/// 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.
95100
#[allocator(allocate_zeroed)]
96101
pub fn allocate_zeroed(size: usize, align: usize) -> *mut u8 {
97102
...
@@ -103,6 +108,8 @@ pub fn allocate_zeroed(size: usize, align: usize) -> *mut u8 {
103108
///
104109
/// The `old_size` and `align` parameters are the parameters that were used to
105110
/// create the allocation referenced by `ptr`.
111+
///
112+
/// This function is required.
106113
#[allocator(deallocate)]
107114
pub fn deallocate(ptr: *mut u8, old_size: usize, align: usize) {
108115
...
@@ -122,6 +129,11 @@ pub fn deallocate(ptr: *mut u8, old_size: usize, align: usize) {
122129
///
123130
/// The `old_size` and `align` parameters are the parameters that were used to
124131
/// 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.
125137
#[allocator(reallocate)]
126138
pub fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 {
127139
...
@@ -155,9 +167,9 @@ The allocator functions must be publicly accessible, but can have any name and
155167
be defined in any module. However, it is recommended to use the names above in
156168
the crate root to minimize confusion.
157169

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.
161173

162174
## Using an allocator
163175

@@ -240,9 +252,47 @@ The allocator APIs could be simplified to a more "traditional"
240252
malloc/calloc/free API at the cost of an efficiency loss when using allocators
241253
with more powerful APIs.
242254

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+
243266
# Unresolved questions
244267
[unresolved]: #unresolved-questions
245268

246269
It is currently forbidden to pass a null pointer to `deallocate`, though this is
247270
guaranteed to be a noop with libc's `free` at least. Some kinds of patterns in C
248271
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

Comments
 (0)