
Guys, Could we please resist complicating interfaces when we do not have to? I personally consider an additional blocking parameter for something like try_lock excessive because it distorts try_lock into becoming scoped_lock. Let's keep different concepts different. Blocking in try_lock is an oxymoron -- try_lock cannot block because it is "try". The basic usages (covering about 80%) are: scoped_lock l(m); // Block until it locks. scoped_try_lock l(m); // Try (!) to lock. I'll check the result. scoped_timed_lock l(m, time); // Block until it locks or time runs out. I'll check the result. Simple and clean. The only functionality that I can see beyond that is when I have to only declare a lock but apply it later. Like: Void Foo() { scoped_lock l(m, do_not_lock); if (something) { l.lock(); // Can't declare here. ... } } For that purpose we'll need something like scoped_lock(mutex&, nolock_t); That's it. Isn't it? Alternatively we might consider making timed_lock our basic lock as scoped_lock and try_lock are merely border-cases (time=infinite and time=0 respectively). Then, scoped_lock and try_lock would be real refinements (convenience interfaces) of that general concept. V. Christopher Currie wrote:
Michael Glassford wrote:
To address these problems, I would like to redefine the lock concept
constructors as follows (changes indicated with "^"):
Definitions ----------- L: lock type l: lock variable (type L) m: mutex variable (appropriate Mutex type) s: initial lock state (enum type {NO_LOCK=0, LOCK=1}) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ b: block? (enum type blocking_state {NON_BLOCKING=0, BLOCKING=1}) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Lock Concept ------------ L l(m,s) //Blocking lock if s L l(m) //Blocking lock
TryLock Concept --------------- L l(m,s,b) //Lock if s; blocking if b ^ ^^^^^^^^^^^^^ L l(m,b) //Lock; blocking if b ^ ^^^^^^^^^^^^^
TimedLock Concept ----------------- L l(m,s,b) //Lock if s; blocking if b ^ ^^^^^^^^^^^^^ L l(m,t) //Blocking lock, failing if not obtained by time t
I like this proposal, if for no other reason than the move to enums makes the arguments clearer. A couple of points:
Yes, I like LOCK and NO_LOCK better than true and false for the same reason.
TryLock: What would be the semantics of l(m, NO_LOCK, b)? In other words, if you're not going to lock on construction, why specify a blocking policy?
The only reason is so that if you write l(m, LOCK, ...) you could also specify the blocking parameter. An expansion of Vladimir Batov's of using structs rather than enums could help here: struct nolock_t {}; nolock_t nolock; struct lock_t {}; lock_t lock; class TryLock { TryLock(TryMutex m, no_lock_t s) {...} TryLock(TryMutex m, lock_t s, blocking_t b) {...} }
L l(m, b) and L l(m, s) seem to cover the two scenarios: either I don't want to lock, or I do and I need to specify
the blocking policy.
TimedLock: I'm not sure I follow the reasons why TimedMutex refines TryMutex. (This is a comment on the original design, not your specific changed, but bear with me.) I think a timeout of zero seconds achieves the same goal, even if TimedLock/TimedMutex don't implement the same operations. So I don't think that TimedLock needs a constructor that takes a blocking argument, and ultimately I think TimedLock/TimedMutex should refine Mutex/Lock, and not TryMutex/TryLock.
Also, the current implementation of TimedLock doesn't support a single argument constructor, even though it is supposedly a refinement of TryLock, which does. I'd like to see TimedLock implemented in such a way that I could use it as if it were a simple Lock, which I currently cannot. In summary, this is what I'd like to see:
Lock Concept --------------- L l(m) //Blocking lock L l(m,s) //Blocking lock if s
TryLock Concept --------------- As Lock, *plus:* L l(m,b) //Lock; blocking if b
TimedLock Concept ----------------- As Lock (not TryLock), *plus:* L l(m,t) //Blocking lock, failing if not obtained by time t //If t == 0, acts as TryLock.
As I said in another post, I'll think about this some more. Thanks for taking the time to comment. Mike