
I'm wondering about the following scenario (with whatever syntax): try_mutex m1; rw_mutex rwm; void foo() { rw_mutex::upgradable_read_lock ur(rwm); ... if (...) { rw_mutex::write_lock w(m, false); // Need to write lock rwm and lock m1 here (for whatever reason) } } This implies a use of lock_both, which requires two try_locks. I can build a generic try_lock to handle transferring from ur to w like so: template <class TryLock1, class TryLock2> class transfer_lock { public: transfer_lock(TryLock1& m1, TryLock2& m2, bool lock_it = true); ~transfer_lock(); void lock(); bool try_lock(); void unlock(); bool locked() const; operator int bool_type::* () const; private: transfer_lock(const transfer_lock&); transfer_lock& operator=(const transfer_lock&); }; This is just an extension of the helper lock class I presented earlier with try_lock functionality added. transfer_lock::try_lock() will need to try to transfer ownership from m2 (the upgradable_read_lock) to m1 (the write_lock) in a non-blocking manner. This will require some additional interface on upgradable_read_lock, possibly: template <class RW_Mutex> class upgradable_read_lock { public: ... bool try_transfer_to(write_lock<mutex_type>& w); ... }; So the end user code might look like: try_mutex m1; rw_mutex rwm; void foo() { typedef rw_mutex::upgradable_read_lock UR; typedef rw_mutex::write_lock WL; typedef transfer_lock<WL,UR> TL; typedef try_mutex::lock OtherLock; UR ur(rwm); ... if (...) { WL w(m, false); TL tl(w, ur, false); OtherLock l1(m1, false); lock_both<TL, OtherLock> lock(tl, l1); // ok, ur unlocked, w locked, and l1 locked, all atomically } } Questions: 1. Does anyone see a disaster (deadlock or otherwise) in trying to do all this atomically? I so far haven't seen any problems, but that doesn't mean much. 2. If there are no problems, does anyone see this use scenario as likely to be needed, or worth the trouble? Notes: This begs the question of adding: template <class RW_Mutex> class read_lock { public: ... bool try_transfer_to(write_lock<mutex_type>& w); ... }; However I strongly recommend against it. Substituting read_lock in for upgradable_read_lock in the previous code: try_mutex m1; rw_mutex rwm; void foo() { typedef rw_mutex::read_lock RL; typedef rw_mutex::write_lock WL; typedef transfer_lock<WL,RL> TL; typedef try_mutex::lock OtherLock; RL r(rwm); ... if (...) { WL w(m, false); TL tl(w, r, false); OtherLock l1(m1, false); lock_both<TL, OtherLock> lock(tl, l1); // error, deadlock possible! } } If two threads try to construct the lock_both simultaneously (which isn't possible with the upgradable_read_lock version) then neither will be able to obtain the write_lock w because each will be holding the read_lock r and refusing to let it go. Therefore I believe the try_transfer_to(write_lock) functionality for read_lock is inherently dangerous and shouldn't be provided. Comments? -Howard