I actually have working code for this problem, but would love to hear any suggestions for a cleaner approach, or if there is a crate that does this, or if it might be good to split it off into a different crate. And now for the problem (and my solution)…
I have a long-running daemon (intended to run for months to years), which spawns threads. These threads must complete (unless power goes down or something), so the main thread must outlive them. In some cases, however, the main thread wants to exit (specifically, when the daemon is restarted due to an upgrade), so it needs to wait for the spawned threads.
As I see it, I have two options. I could either store
JoinHandles and join all the threads, or use something like a semaphore to count them. The former approach seems awkward, since I never want to wait on the threads until I’m exiting, and if I only wait when I exit then I have a resource leak due to threads accumulating. The latter is made somewhat more challenging due to
Semaphore being eliminated, so I need to use
Condvar, which so far as I can tell is the correct thing to do.
I thought about just creating a semaphore (which in effect I did), but instead decided to create a
Threads struct that would spawn the threads, wrapping each spawned function in a closure that decrements the thread count. Then I implemented a
Drop on the
Threads struct which waits until the count gets to zero. This seems like a pretty reusable bit of code (possibly needing better names), so I am curious what y’all think of it.
This is my first time using
Condvar so it seems possible I’ve gotten something wrong. It’s also possible there is a conceptual problem here. And I wonder if there is a common pattern (or crate implementing some such pattern) for this sort of use case that I could do better to use instead? It seems odd writing such low-level and (to me) fiddly code for something as simple as waiting for the job threads to complete!
Here is the code in question: