There's currently no easy way in the API to recover the allocation extent (aka the "usable_size", aka the maximum "fit" value, etc).
As one example, the allocation may have initially been performed by a type which doesn't have the ability to store the capacity information, for example allocating a Box<[T]> and converting to a Vec, as done in the vec![] macro.
Additionally, for many allocators, an explicit request to shrink an allocation will either do nothing, or only do something if it would change size classes. So it's completely plausible that the Vec::from code in Vec::from(a_vec.into_boxed_slice()) could have a lot to gain by querying the usable allocation size.
Right now, I believe the closest way of getting at this information is immediately invoking AllocRef::grow with a new_size parameter equal to layout.size() but this is opaque, potentially slow, and confusing.
IMO, Adding an explicit function to return the usable size if known would be better. Here's a bikeshed:
ptr must have been allocated by this allocator and not have been deallocated.
None is returned by default, and indicates that the allocator does not support this. Returning None here does not mean it's legal to pass incorrect layouts to dealloc — and users are strongly encouraged not to unwrap the result.
If Some(size) is returned: layouts/blocks with a size of size are now considered to "fit" the allocation.
For AllocRef impls: It's legal for the returned size to be anything between [the size that was used to request the allocation] to [the actual maximum usable size of the allocation]. Returning a value outside this range is forbidden.
Importantly, returning a usable size value less than the previous maximum usable size does not reduce that maximum value. The intention here is: This function doesn't change the size of allocations although it can reveal that the size bound returned earlier was lower than the actual usable size.
This might seem too subtle, but it allows some currently allowed and potentially desirable implementations to remain legal and efficient:
For example: it's legal* to implement AllocRef::alloc by checking a malloc_good_size** function and passing its result to the allocation function, rather than calling malloc_usable_size on the allocation functions result.
The wording above intends to continue to allow that, and allow AllocRef::usable_size to be implemented using the more accurate malloc_usable_size call. (which is possibly slower than good_size, but almost certainly faster than reallocating).
Note: This also ties in with https://github.com/rust-lang/wg-allocators/issues/74, but they're useful independently, and not particularly useful together — the "together" functionality is provided by the current API, as the caller should just use one of the functions that provides both the size and pointer as a result.
* That is, it's legal iff the underlying allocator can handle the differences in Layout passed to its dealloc, which is something you know as the implementer of the AllocRef trait.
** For some allocator implementations this is meaningfully better (good_size might just round up), and only different in rare cases (for example, for huge allocation made directly to the OS where the allocator switches to a different size granularity).
There's currently no easy way in the API to recover the allocation extent (aka the "usable_size", aka the maximum "fit" value, etc).
As one example, the allocation may have initially been performed by a type which doesn't have the ability to store the capacity information, for example allocating a
Box<[T]>
and converting to aVec
, as done in thevec![]
macro.Additionally, for many allocators, an explicit request to shrink an allocation will either do nothing, or only do something if it would change size classes. So it's completely plausible that the
Vec::from
code inVec::from(a_vec.into_boxed_slice())
could have a lot to gain by querying the usable allocation size.Right now, I believe the closest way of getting at this information is immediately invoking
AllocRef::grow
with anew_size
parameter equal tolayout.size()
but this is opaque, potentially slow, and confusing.IMO, Adding an explicit function to return the usable size if known would be better. Here's a bikeshed:
ptr
must have been allocated by this allocator and not have been deallocated.None is returned by default, and indicates that the allocator does not support this. Returning None here does not mean it's legal to pass incorrect layouts to dealloc — and users are strongly encouraged not to unwrap the result.
If
Some(size)
is returned: layouts/blocks with a size ofsize
are now considered to "fit" the allocation.For
AllocRef
impls: It's legal for the returned size to be anything between [the size that was used to request the allocation] to [the actual maximum usable size of the allocation]. Returning a value outside this range is forbidden.Importantly, returning a usable size value less than the previous maximum usable size does not reduce that maximum value. The intention here is: This function doesn't change the size of allocations although it can reveal that the size bound returned earlier was lower than the actual usable size.
This might seem too subtle, but it allows some currently allowed and potentially desirable implementations to remain legal and efficient:
For example: it's legal* to implement
AllocRef::alloc
by checking amalloc_good_size
** function and passing its result to the allocation function, rather than callingmalloc_usable_size
on the allocation functions result.The wording above intends to continue to allow that, and allow
AllocRef::usable_size
to be implemented using the more accuratemalloc_usable_size
call. (which is possibly slower than good_size, but almost certainly faster than reallocating).Note: This also ties in with https://github.com/rust-lang/wg-allocators/issues/74, but they're useful independently, and not particularly useful together — the "together" functionality is provided by the current API, as the caller should just use one of the functions that provides both the size and pointer as a result.
* That is, it's legal iff the underlying allocator can handle the differences in
Layout
passed to itsdealloc
, which is something you know as the implementer of the AllocRef trait.** For some allocator implementations this is meaningfully better (good_size might just round up), and only different in rare cases (for example, for huge allocation made directly to the OS where the allocator switches to a different size granularity).