
On Jul 5, 2004, at 5:43 PM, Peter Dimov wrote:
Howard Hinnant wrote:
I'm not following that x==y always holds. If two threads concurrently hold a read lock, and concurrently try to obtain a write lock, only one thread will get the write lock, the other will block. Assuming the one thread that got the write lock changes x, then the thread that blocked will fire its assert when it finally unblocks and gets the write lock.
What am I missing?
As I understand it, if two threads hold a read lock, no thread can obtain a write lock. Write lock == exclusive access. This corresponds to the POSIX memory model where write accesses must be exclusive, but read accesses can be shared with other read accesses. But I may be wrong. ;-)
So in: void f(read_write_mutex m) { read_write_mutex::read_lock r(m); int y = x; if (...) { read_write_mutex::write_lock w(r); //lock promotion what would happen here if two threads entered f and tried to construct w simultaneously? My take, depending upon how the w(r) constructor is implemented, is either: 1. deadlock. 2. one thread blocks and one thread gets the lock. Imho choice 1 is a buggy implementation of the w(r) constructor. And choice 2 results in the assert(x==y) possibly firing. I believe choice 2 is the only reasonable path. And I also believe that the syntax above might lull a code reader into believing that assert(x==y) should always be true. And therefore I think the following (more explicit) syntax is superior: void f(read_write_mutex m) { read_write_mutex::read_lock r(m); int y = x; if (...) { r.unlock(); read_write_mutex::write_lock w(m); This is essentially how the w(r) ctor must be implemented, if it is to be implemented at all. One could try a try_lock on w if the read count is 1, and then fall back on the above if that doesn't work, but I'm unsure if that really provides a benefit. -Howard