[thread] Shared Mutex views?

Is there any plan to implement something like this: http://www.neuromancy.net/fisheye/browse/mantra/trunk/Mantra-I/mantra/ utils/shared_mutex_views.h?r=435 So that a shared mutex can be operated like a normal mutex, including scoped_lock behavior, and you can choose whether that scoped_lock behavior should be to acquire an exclusive, a shared, or an upgrade lock? The idea being: // somewhere else shared_mutex smtx; // Where I need it: shared_mutex_view smv(smtx); shared_mutex_view::scoped_lock sl(smv); // ... // OR: exclusive_mutex_view smv(smtx); exclusive_mutex_view::scoped_lock sl(smv); Right now, shared_mutex only has primitives, and cannot be used with things like scoped_lock (aka. unique_lock). Additionally, it cannot be used as a condition, despite the condition framework. These views would facilitate that, however I'll admit, I've not thought of all the implications of such things. PreZ :)

On Nov 14, 2007, at 3:53 PM, Preston A. Elder wrote:
Is there any plan to implement something like this:
http://www.neuromancy.net/fisheye/browse/mantra/trunk/Mantra-I/mantra/ utils/shared_mutex_views.h?r=435
So that a shared mutex can be operated like a normal mutex, including scoped_lock behavior, and you can choose whether that scoped_lock behavior should be to acquire an exclusive, a shared, or an upgrade lock?
The idea being:
// somewhere else shared_mutex smtx;
// Where I need it:
shared_mutex_view smv(smtx); shared_mutex_view::scoped_lock sl(smv); // ...
// OR: exclusive_mutex_view smv(smtx); exclusive_mutex_view::scoped_lock sl(smv);
Right now, shared_mutex only has primitives, and cannot be used with things like scoped_lock (aka. unique_lock). Additionally, it cannot be used as a condition, despite the condition framework. These views would facilitate that, however I'll admit, I've not thought of all the implications of such things.
I'm not sure I see the purpose of:
exclusive_mutex_view smv(smtx); exclusive_mutex_view::scoped_lock sl(smv);
because actually unique_lock<shared_mutex> should work just fine (and has semantics similar to what you indicate for exclusive_mutex_view). And condition_variable_any::wait works with unique_lock<shared_mutex> just fine as well. That covers exclusive locking for shared_mutex. For shared locking what you have for shared_mutex_view is very similar to the shared_lock<Mutex> template proposed here: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2406.html#shared_mu... Differences include: shared_mutex_view works only for shared_mutex. shared_lock works for any type supporting the shared_mutex interface (such as a user-written interruptible_shared_mutex). It is easier (syntactically) to convert ownership modes using lock conversion syntax. For example: upgrade_mutex mut; unique_lock<upgrade_mutex> lk(mut); // mut exclusive locked here shared_lock<upgrade_mutex> slk(move(lk)); // mut share locked here I.e. the locks provide the "homogenized view", and add the ability to move and convert the mutex ownership, also with a homogenized syntax. The homogenized syntax for moving and converting mutex ownership enables extremely simple implementations of "generic lock conversion algorithms" (such as transfer_lock also in N2406). And all of the lock/mutex combinations work with condition_variable_any (which only requires lock/unlock and everything has that). shared_mutex mut; condition_variable_any cv; void wait_in_shared_ownership_mode() { shared_lock<shared_mutex> shared_lk(mut); // mut is now shared-locked // ... while (not_ready_to_proceed()) cv.wait(shared_lk); // shared-lock released while waiting // mut is now shared-locked // ... } // mut is now unlocked void wait_in_unique_ownership_mode() { unique_lock<shared_mutex> lk(mut); // mut is now unique-locked // ... while (not_ready_to_proceed()) cv.wait(lk); // unique-lock released while waiting // mut is now unique-locked // ... } // mut is now unlocked upgrade_mutex mut2; void wait_with_transfer_from_unique_to_shared_ownership() { upgrade_lock<upgrade_mutex> slk(mut2); // mut2 is now share-locked // ... if (I_need_to()) { transfer_lock<unique_lock<upgrade_mutex>, upgrade_lock<upgrade_mutex>> lk(slk); // mut2 is now unique-locked // ... while (not_ready_to_proceed()) cv.wait(lk); // mut2 share-locked while waiting // mut2 is now unique-locked // ... } // mut2 is now share-locked // ... } // mut2 is now unlocked -Howard

On Wed, 14 Nov 2007 16:41:12 -0500, Howard Hinnant wrote:
I'm not sure I see the purpose of:
exclusive_mutex_view smv(smtx); exclusive_mutex_view::scoped_lock sl(smv);
because actually unique_lock<shared_mutex> should work just fine (and has semantics similar to what you indicate for exclusive_mutex_view). And condition_variable_any::wait works with unique_lock<shared_mutex> just fine as well. That covers exclusive locking for shared_mutex.
This was just for completeness. If I was going to have something_view for the others, I may as well have one for exclusive, even if its redundant.
For shared locking what you have for shared_mutex_view is very similar to the shared_lock<Mutex> template proposed here:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/ n2406.html#shared_mutex
Good to know - this is why I asked. I figured a more complete and well thought-out system (I knocked the above file out in about 10 minutes) was coming. Thanks for the info.
upgrade_mutex mut; unique_lock<upgrade_mutex> lk(mut); // mut exclusive locked here shared_lock<upgrade_mutex> slk(move(lk)); // mut share locked here
This is nice, but: 1) I can easily see the terms shared_mutex and shared_lock getting confused. 2) shared_lock and upgrade_lock are both templates - which is not so bad by itself, a simple typedef can make 'concrete' versions. But it looks weird to do unique_lock<shared_mutex> or unique_lock<shared_lock<shared_mutex> > for example. 3) The implementation as specified uses c++-0x features, and the liklihood is 1.35 will be released before c++-0x, and most compilers will not support these features soon (yes, I know GCC will next version). So we need a solution that does not use things like rvalue reference. And 4) none of these interfaces have a scoped_lock / scoped_try_lock / scoped_timed_lock typedef in them. Many people (myself included) are used to the interface of boost::lock_type::scoped_lock sl(lock); I don't know if this is being deprecated or not, but it is very prevalent.
void wait_in_shared_ownership_mode() { // ... } // mut is now unlocked
void wait_in_unique_ownership_mode() { // ... } // mut is now unlocked
upgrade_mutex mut2;
void wait_with_transfer_from_unique_to_shared_ownership() { // ... } // mut2 is now unlocked
All of these though can be achieved without c++-0x. The equivalent in my interface is to create a shared_mutex, and then create one of my view classes (which just hold a reference). I called them views because they don't hold any data themselves, but are used to treate the shared_mutex in a specific way (ie. as a shared-only lock, etc). All of mine work with conditions just as this interface and could easily be templatized to work with anything supporting the shared_mutex interface easily enough. But it doesn't require c++-0x :) So my original question stands, is there something coming in boost::thread that will work with existing compilers that implements the functionality of either my link or Howard's for boost 1.35? and if so, when will we get to play with it (or at least see something close to the final interface, even if not exact)? PreZ :)
participants (2)
-
Howard Hinnant
-
Preston A. Elder