
Matt Hurd wrote:
Michael Glassford
Matt Hurd wrote:
If I read this correctly, it's an objection to the idea of promotion in general (except for the special case of a promoteable shared lock),
Yep, promotion is generally poor practice in my book as you have to try hard if you don't want to deadlock or end up with a false economy. Having a special mutex/lock that supports it is my preferred option for keeping it away from normal behaviour. "It's over there in the closet if you really insist..." ;-)
in which case I tend to agree; however, I want to specify the syntax that promotion would use even if the Boost.Threads shared_mutex ends up not using it, because I want to allow custom shared_mutex classes that do use it to be used with Boost.Threads lock classes (better support for custom classes being used with Boost.Threads classes is something I plan to cover in a later posting).
It still not clear to me how the lock transfers operate under simultaneous requests.
"Transfer" from a mutex is really just a delayed call to a lock method, so I don't see a problem: if there are simultaneous requests, one blocks and the other doesn't. Transfer from a lock shouldn't happen simultaneously (locks, by design, are not thread-safe), so that shouldn't be a problem either.
What does the transfer object buy you over:
That is,
why l = m.promote(l.transfer());
l = m.promote(l);
In this case, the .transfer() isn't really necessary; if people prefer, it could be omitted. In the case of actually transfering from one lock to another, I think it's best require the .transfer() in order to make the transfer explicit.
By the way I think the l is a bad name to use in examples as it is hard to see 1 l for I. lk might be better short hand.
You're right; sorry.
I agree with your push to clean up the lock constructor interface. I currently wrap them all and use my own interface so I can have generic code for null, exclusive and shared ops.
Not sure about the lock transfer object as it is really just another name for a lock. After all it is the token representing the locked state, or a lock by another name... Perhaps just being able to return a lock from a mutex and being able to transfer ownership by copying a lock like an auto ptr would give you the same thing. I need to think about this some more.
Except that lock objects can only be transferred explicitly by calling their transfer() method and have public constructors, while lock_transfer objects transfer implicitly and can only be constructed by mutex and lock objects. You can't tell this from what I posted, however.
Should locks really be transferable or should shared_ptr< lock > be the idiom if you want to go beyond scoping?
Importantly, I believe you need to be able to request a share lock even of an exclusive mutex or null mutex so that you can write generic concurrent code. You write to a shared model and the other models work.
I was intending to have better support for generic code, though I planned to cover that in a later posting.
What happens when you request a shared lock from a non-shared mutex? It just gives you an exclusive lock?
Yes. It works just dandy as the precondition is weaker and the post condition is stronger.
OK. Just wanted to be sure I understood you.
In a similar vein, shared and exclusive do nothing on the null mutex. Write to a shared model and get non-concurrent and exclusive model behaviour also. This is only possible if you write to a shared model as there is no real way to write from a simpler model and have sharing introduced automagically.
I understand.
As an aside, I guess writing to a promotable shareable model would like wise be substitutable back if the promotion always fails (shareable model) or always succeeds (exclusive model).
This gives you a substitutable taxonomy of null->exclusive->shareable->promotable.
Write the appropriate model and the "lesser" models work making architectural components much more flexible.
Similar thing to what ACE has been doing for over a decade...
Mike