[Thread] Trying to share a mutex between objects
Hi all, I'm having some trouble getting my head around Boost mutexes and how they work. Basically I have a handful of objects, and they all use a shared resource (a C-style function.) The function isn't thread-safe, so I want to protect it to ensure only one thread at a time can call it. My idea was to create a mutex for this (lock before the call, unlock after it), but I'm having trouble working out how to share the mutex between all the objects. The boost::mutex object seems like what I want, but it's non-copyable so I can't share it among multiple objects. I tried passing around references to the mutex instead, but this just triggers an assertion failure when I try to lock it. Should I be using boost::mutex for this? How would you normally serialise access among different objects like this? I'm finding the examples somewhat tricky to work from, as most of them use global variables and C-style functions for creating threads, which doesn't really fit with the C++ model of my program - I could just make the mutex a global variable but it doesn't seem like the cleanest solution to me. Any pointers would be much appreciated. Thanks, Adam.
I tried passing around references to the mutex instead, but this just triggers an assertion failure when I try to lock it.
Oh my bad, I just realised the function I'm trying to protect was failing, causing the main code to terminate early...which of course resulted in the mutex being destroyed, while the threads were still using it... It looks like it all works fine passing around references to the same boost::mutex object. Sorry for the noise! Cheers, Adam.
Adam Nielsen wrote:
Basically I have a handful of objects, and they all use a shared resource (a C-style function.) The function isn't thread-safe, so I want to protect it to ensure only one thread at a time can call it.
My idea was to create a mutex for this (lock before the call, unlock after it)... I tried passing around references to the mutex ...
Should I be using boost::mutex for this? How would you normally serialise access among different objects like this? I'm finding the examples somewhat tricky to work from, as most of them use global variables and C-style functions for creating threads, which doesn't really fit with the C++ model of my program - I could just make the mutex a global variable but it doesn't seem like the cleanest solution to me.
I think I'd probably create a class to manage access to the shared function. The class would contain the mutex, and the method that calls the C function would instantiate the lock object. Nobody else would directly call the C function any more. That approach generalizes to a family of related functions, plus whatever persistent data they might need. There are a couple of different ways to instantiate the wrapper class. One is to use the Singleton pattern. Note that Boost accepted a Singleton library a couple months ago, which hasn't yet made it into an official Boost release; check the vault for the current version. Singleton is essentially a global with a bit of protection. But that might be an acceptable way to manage a global resource (your C function). Since you already have a way to pass mutex references to your handful of objects, though, you could pass a reference to your wrapper object instead. But then you have to figure out where the shared wrapper object lives, and who's responsible for its lifespan. I'd probably allocate it on the heap, pointing to it with a boost::shared_ptr. Store a copy of that boost::shared_ptr in each of your handful of objects. Ownership is shared among them, and the last one to leave turns out the lights.
My idea was to create a mutex for this (lock before the call, unlock after it)... I think I'd probably create a class to manage access to the shared function. The class would contain the mutex, and the method that calls the C function would instantiate the lock object. Nobody else would directly call the C function any more.
I ended up reaching the same conclusion here, as I wanted to store other persistent data too (in this case a counter for the number of times the function was called) and wrapping it all up in a class does make it cleaner, as you suggest.
Since you already have a way to pass mutex references to your handful of objects, though, you could pass a reference to your wrapper object instead.
Yes, I think I prefer this method, as I would rather choose to only have one instance of the class floating around, as opposed to using a Singleton pattern with its additional complexity to enforce this rule. (I'd never heard of the Singleton pattern before - interesting!)
I'd probably allocate it on the heap, pointing to it with a boost::shared_ptr. Store a copy of that boost::shared_ptr in each of your handful of objects. Ownership is shared among them, and the last one to leave turns out the lights.
I agree - however this time it will be around for the life of the (fairly simplistic) program, so it'll be just as easy to create it as a local variable in main(), wait for the threads to terminate and then have it destroyed automatically. Thanks for your reply! Cheers, Adam.
participants (2)
-
Adam Nielsen
-
Nat Goodspeed