Crate discard [−] [src]
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:
1) 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.
2) 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
:
1) std::mem::forget
leaks all of the memory,
DiscardOnDrop::leak
leaks the minimal
amount of memory: unused memory is properly cleaned up.
2) With std::mem::forget
you cannot
clean up a value after it has been leaked, but with
DiscardOnDrop::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.
Structs
DiscardOnDrop |
If you have a value which implements |
Traits
Discard |
This trait is very similar to |