
Matthew Vogt wrote:
Michael Glassford <glassfordm <at> hotmail.com> writes:
Translating this to the constructor model of promotion would have to look something like this, I guess:
void f(read_write_mutex& m) { read_write_mutex::try_read_lock r(m);
//do "read stuff"
read_write_mutex::try_write_lock w(r, /*maybe a parameter here to use try_promote() instead of promote()*/);
if (!w.locked()) { r.unlock(); w.lock(); //redo some of "read stuff" }
//do write stuff }
You could encapsulate some of that in the constructor of the write lock:
void f(read_write_mutex& m) { read_write_mutex::read_lock r(m);
do_read_stuff();
read_write_mutex::write_lock w(r); // Upgrade, releasing and re-acquiring // if necessary if (!w.atomically_promoted()) { do_read_stuff(); }
do_write_stuff(); }
It certainly looks error-prone, by requiring a test and the repetition of the earlier code. Makes you wonder if it should have a function to execute on non-atomic upgrade:
{ read_write_mutex::read_lock r(m);
do_read_stuff();
read_write_mutex::write_lock w(r, bind(this, &class::do_read_stuff));
do_write_stuff(); }
You could reduce further, but I'm sure it will collapse under the weight of real code :)
However, I don't see any way to avoid re-trying after the write-lock is obtained when promotion fails, and I don't see a way to prevent promotion from failing except for the suggested latent-read-lock / upgradeable-read-lock. I agree that such a lock is a good idea, but it does have the drawback of serializing all upgradeable read locks, which could be quite undesirable in some circumstances. Mike