Execute method when RwLockWriteGuard gets drop()ed

I have a method which hands out a RwLockWriteGuard. When the calling method has finished its modification it drops the Guard. After that a second method has to be called.

Pseudocode:

{
    let mut item: RwLockWriteGuard<_> = broker.get_item();
    item.modify();
    // guard dropped here
}
broker.finalize();

Rather than calling finalize() by hand I want it to be called automatically after the guard gets dropped.
Is that possible?

I thought about creating a wrapper type around the RwLockWriteGuard and implement the Drop-trait. But the order would be wrong: First my object’s drop method would be called; then the guard would be dropped.

You can use ManuallyDrop in your wrapper to fix the drop order problem.

1 Like

Thank you a lot for that quick and helpful response!
I didn’t know about that type - will try to integrate this in my real-world code.

Instead of returning a RwLockWriteGuard, you can return a wrapper type that implements Deref, DerefMut, and Drop. In Drop it can call finalize. This way you don’t have to fiddle with unsafe code.

struct Wrapper<'a, 'b, T: ?Sized>(&'a Broker, RwLockGuard<'b, T>);

impl<T: ?Sized> Deref for Wrapper<'_, T> {
    type Target = T;
    
    fn deref(&self) -> &T { &self.1 }
}

impl<T: ?Sized> DerefMut for Wrapper<'_, '_, T> {
    fn deref_mut(&mut self) -> &mut T { &mut self.1 }
}

impl<T: ?Sized> Drop for Wrapper<'_, '_, T> {
    fn deref_mut(&mut self) -> &mut T {
        self.0.finalize();
    }
}
1 Like

This is what I had before, but it results in the wrong drop order.

Ah, ok

While ManuallyDrop is probably the correct path. Before that was in stable Rust an alternative was to store the MutexGuard as an option. Then in the drop for wrapper Option::take the guard out of the Option field and drop it either with a scope or std::mem::drop. That does make using the guard a bit harder since it needs to be matched or unwrapped to be used.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.