
Part of the point, though, is that try_lock doesn't actually work that way: one of the try_lock constructors does a non-blocking try_lock(), and the other does a blocking lock(). Without looking, do you always remember which one does which? I don't.
Well, first, the behavior that I was talking about in my prev. email (ones I was happy about) were the 'basic' constructors (that I called 'default' constructors -- what an embarassment). The following is IMHO good and I would not like see them complicated: 1. scoped_lock l(m); // Blocks until it locks. 2. scoped_lock l(m, true); // As above. 3. scoped_lock l(m, false); // Only declaration. Does nothing. Needed if I need to declare but use it later. 4. try_lock l(m); // Tries to lock. Always falls through. I need to check the result. 5. try_lock l(m, false); // Only declaration. Does nothing. 6. timed_lock l(m, time); // Blocks until locks or 'time' expires. 7. timed_lock l(m, false); // Only declaration. Does nothing. I have to agree that the following behavior 8. try_lock l(m, true); 9. timed_lock l(m, true); that according to the documentation call lock() instead of respective try_lock() and timed_lock() look wrong. I'd be temted to say that merely making (8) work as (4) would be sufficient fo fix try_lock. (9) does not appear "fixable" in a similar way. I am tempted to suggest something similar to overloaded 'operator new': struct nolock_t {}; nolock_t nolock; 1. scoped_lock l(m); 2. scoped_lock l(m, nolock); 3. try_lock l(m); 4. try_lock l(m, nolock); 5. timed_lock l(m, time); 6. timed_lock l(m, nolock); It removes redundancy (as with the original scoped_lock(m) and scoped_lock(m, true)) and makes everything simple and consistent. Just a thought. V