Open FeldrinH opened 4 months ago
28M recent downloads, so it qualifies as popular at least...
I ran into this recently but I'm honestly not much of a fan, feels more idiomatic (and not much more verbose) to just define a guard type with a Drop
impl.
I guess it's a matter of taste. I personally like it because it allows me to have cleanup logic in the method body, close to the rest of the method code, rather than in a separate Drop impl. I find it more readable than the alternatives for cleanup logic that is specific to one method.
I personally like it because it allows me to have cleanup logic in the method body, close to the rest of the method code, rather than in a separate Drop impl
This. It makes it more readable and eliminates the boilerplate.
scopeguard
also has the very nice guard_on_unwind()
which can be used to detect panic in code you don't fully control, and do cleanup there. Here is an example from our code base where we ensure that the program doesn't annoyingly hang in case of a panic in a worker thread:
thread::Builder::new()
.name(format!("proc #{}", thread_index))
.spawn_scoped(s, move || {
let _on_panic = scopeguard::guard_on_unwind((), |()| {
abandon_reading.store(true, Ordering::Relaxed);
});
worker::<S>(thread_index, session, db);
})
Of course, the worker thread doesn't normally panic, but it was known to happen due to a bug. The above shouldn't be taken as advocating panic as substitute for error handling - the idea is to show how scopeguard can be used to prevent one type of failure (program exit due to panic) turning into a much more annoying one (program hanging due to panic).
A utility/language extension that I quite like and which seems to be fairly commonly used (looking at the numbers on crates.io) is scopeguard, which adds a helper function and convenience macro for deferred cleanup actions (similar to the
defer
statement in Go).