I'm writing my first piece of unsafe code and would really appreciate some other eyes on this if anyone has the time. I've moved it to its own module (https://github.com/Nashenas88/coi/blob/15bfa293d01bfb67e335d31b06827c3059c3c42f/src/resolvable.rs) to limit the scope of unsafe.
What I'm trying to accomplish with that code:
This is for a dependency injection crate, and I'm supporting multiple threads possibly attempting to resolve the same item at the same time. In the past I dealt with this by hiding the resolutions behind a lot of mutexes, but it was hard to manage properly, and prone to deadlocks whenever I would make any sort of involved change.
I switched to using an atomic u8 to manage the states of resolution: unresolved, building, and resolved. The idea I had was that a single thread could guarantee that it's the one doing the building by validating that it is able to update the atomic, and in doing so, I could use
UnsafeCell to ensure that no other thread is writing. However, I also needed to make sure that no other thread attempts to read the value in the
UnsafeCell during the building time, so there's also a
(Mutex<bool>, Condvar) tuple that's used to block all other threads until the building is done, and the value has been resolved. This way I can ensure all of the other threads are notified at once and the CPU isn't blocked with busy waiting.
I wanted to know if I may have gone overboard and don't need unsafe. Have I gotten too much tunnel vision and maybe I'm missing something more obvious?