5 stable releases
Uses old Rust 2015
1.0.4 | Sep 17, 2018 |
---|---|
1.0.3 | Feb 25, 2018 |
#351 in Memory management
95,793 downloads per month
Used in 637 crates
(11 directly)
14KB
131 lines
Discard trait which allows for intentionally leaking memory.
See the documentation for more details.
lib.rs
:
There are situations where you need to intentionally leak some memory but not other memory. This crate can help!
But before I explain, you are probably wondering: why would I want to leak memory in the first place?
There are certain rare situations where leaking memory is either desirable or necessary.
As an example, let's say I am using stdweb, which lets me use JavaScript APIs in Rust.
So I write some code like this:
node.add_event_listener(|event: ClickEvent| {
// ...
});
Seems reasonable, right? But there's a problem: the add_event_listener
method
returns an EventListenerHandle
, and when the EventListenerHandle
is dropped it
will remove the event listener.
Because I'm not using the EventListenerHandle
, it is immediately dropped, so it
receives no events!
Okay, no problem, just use std::mem::forget
:
// This will automatically remove the event listener when `handle` is dropped
let handle = node.add_event_listener(|event: ClickEvent| {
// ...
});
// Now it will no longer remove the event listener
std::mem::forget(handle);
Now the event listener will remain alive forever, which is what I want.
But there's two problems with this:
-
I want it to keep the event listener alive forever, but I also want it to clean up any unused internal memory. Using
std::mem::forget
causes it to leak all of the memory, which is wasteful. -
There are situations where I want to leak the event listener, and then later unleak it. That's not possible with
std::mem::forget
.
The solution to all of these problems is:
-
The
EventListenerHandle
should not implement theDrop
trait. -
The
EventListenerHandle
should implement theDiscard
trait instead. -
The
add_event_listener
method should returnDiscardOnDrop<EventListenerHandle>
.
Now let's look at what is possible:
// This will automatically remove the event listener when `handle` is dropped
let handle = node.add_event_listener(|event: ClickEvent| {
// ...
});
// Now it will no longer remove the event listener, this is similar to `std::mem::forget`
let leaked = DiscardOnDrop::leak(handle);
// Now it will remove the event listener, even though it was leaked
leaked.discard();
There's two huge differences between DiscardOnDrop::leak
and std::mem::forget
:
-
std::mem::forget
leaks all of the memory,DiscardOnDrop::leak
leaks the minimal amount of memory: unused memory is properly cleaned up. -
With
std::mem::forget
you cannot clean up a value after it has been leaked, but withDiscardOnDrop::leak
you can manually discard the value even after it has been leaked.
Most of the time you don't need to worry about any of this:
DiscardOnDrop
will automatically call
discard
when it is dropped, so in that situation
Discard
behaves the same as Drop
.
So you can use normal Rust idioms, and everything works as you would expect. You only need to
worry about Discard
when you need to intentionally leak some memory.