New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RAII for Limits.max_alloc
#2086
Comments
So I've prototyped the
It is possible to put |
On Discord, moulins suggested enforcing stacking of struct Limits<'a>(...);
impl<'a> Limit<'a> {
#[must_use]
pub fn reserved(&mut self, bytes: usize) -> ImageResult<Limits<'_>>;
} |
I think it would be easier to think about this in the context of a specific decoder's use of the One other thing from looking at the |
I'll work on adding limits to animation decoders such as GIF using the existing API, then see if there's any benefit to changing it once we have more internal use of the |
Right now the
Limits
struct provides methods to reserve and free memory from within its memory budget by calling.reserve()
and.free()
. This is a powerful API, but it is easy to forget to write.free()
exactly once with the right amount in all error paths. It will also not be invoked on panic.Possible solutions
This is essentially the same problem as memory allocation in C. It is solved with drop guards: instead of requiring the programmer to call
free
, the reserving function returns a type that frees automatically once it is dropped for any reason - end of scope, errors and panics are all covered.A straightforward drop guard must maintain a reference to the original value; this conflicts with Rust's ownership system and the API of
ImageDecoder.set_limit()
acceptingLimits
rather than a borrow of it. We could make it accept&Limits
and immediately clone . But that would require an API break. This crate provides a template for what drop guards could look like.We might be able to get away with a simpler design: instead of mutating an instance of
Limits
withreserve
/free
calls that must match, we can deprecate those and make a single method,.reserved()
or something, that returns a new#[must_use]
instance ofLimits
with that much lessmax_alloc
. That new instance can then be passed down the call stack. Then we never run into the need to call.free()
because the modified copy is subject to RAII and the original is still around, untouched.The text was updated successfully, but these errors were encountered: