Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Near the end, the blog posts mentions patterns to avoid accidental deadlocks in structs that wrap a Mutex. Here's another one that I like use:

    struct FooInter {
        actual_data: HashMap<...>,
    }

    impl FooInner {
        fn do_something(&mut self) { ... }
    }

    pub struct Foo(RwLock<FooInner>);

    impl Foo {
        pub fn do_something(&self) {
            self.0.write().do_something();
        }
    }
The rule is that FooInner doesn't know about the lock (so calling other methods is safe), while Foo methods can't call other Foo methods (so you can't lock anything twice). You can even move Foo and FooInner to different modules to hide FooInner's contents from Foo, though I rarely find that necessary.

I know this is subjective, but for me, this works better than what the blog post suggests -- at least, I haven't gotten it wrong by accident yet.



Kudos! I've been successfully applying this pattern in a bunch of places and am happy to report that it is very useful and easy to reason about. It works well in any context where your object access is mediated... Mutex & RwLock, Rc and Arc, etc.

I can recommend the ambassador crate to go with this pattern -- it can be very useful for avoiding boilerplate for the newtype struct.

Really the hardest part is naming... I've also settled on FooInner, but I'm still not entirely happy with that convention.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: