
Peter Dimov wrote:
Michael Glassford wrote:
Also, you could end up with some interesting situations like this:
void f(read_write_mutex m) { read_write_mutex::read_lock r(m); if (...) { read_write_mutex::write_lock w(r); //lock promotion //... } //Point A }
The most obvious implementation of promotion would be for the write lock to unlock the read lock if promotion succeeded, but leave it locked if promotion failed. But in the above code, this would mean that if promotion succeeds, neither lock will be locked at "Point A"; however if promotion fails, r will still be read-locked at point A.
Not necessarily, ~write_lock can (should) demote the lock back to read (or whatever the initial condition of r was).
True. But then, in the reverse case: void f(read_write_mutex m) { read_write_mutex::write_lock w(m); if (...) { read_write_mutex::read_lock r(w); //lock demotion //... } //Point A } It may not be possible for r's destructor to re-obtain the write lock, which means that, at point A: 1) If the write lock can be re-obtained, w is write-locked. 2) Otherwise, w is either unlocked or read-locked. The idea of a write-lock being read-locked is pretty strange, but having it unlocked doesn't seem a good choice, either. I realize that a combined read-write lock has the same problem of possibly being unable to re-obtain the write-lock, but in that case it is at least more obvious that the lock state changed and what it changed to: void f(read_write_mutex m) { read_write_mutex::read_write_lock l(m, write_locked); if (...) { l.demote(); //lock demotion //... } //Point A: l is read-locked } Or: void f(read_write_mutex m) { read_write_mutex::read_write_lock l(m, write_locked); if (...) { l.demote(); //lock demotion //... l.try_promote(); //optional } //Point A: l is write-locked if try_promote() succeeded, //read-locked if it failed; never unlocked. } Finally, to take two more realistic use cases: void f(read_write_mutex m) { read_write_mutex::write_lock w(m); //... read_write_mutex::read_lock r(w); //lock promotion //... } And: void f(read_write_mutex m) { read_write_mutex::write_lock r(m); //... read_write_mutex::read_lock w(r); //lock demotion //... } The second lock does unnecessary work in demoting/promoting the lock for the first lock, which then immediately unlocks it. Don't get me wrong: I actually like the idea of separate read and write locks, but there seem to be some tricky problems to address to make them work with lock promotion/demotion. Mike