
Doug Gregor wrote:
On Tuesday 29 June 2004 8:00 am, Christopher Currie wrote:
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.
I disagree here, as well. Say I want to program generically...
template <typename Mutex, typename Lock> class worker_class { Mutex m_;
public: do_work() { Lock l(m_); // Does this call block? // am I guarenteed to be locked here? } }
Yes, it's a contrived case,
I don't believe it is a contrived case. Certainly once we have read/write mutexes we're going to want to tell generic components which kind of lock they need to use.
I was going to ask if locks were likely to be used generically in this way; obviously they will, in your opinion. I appreciate your bringing up read/write locks; I was planning to bring them into the discussion as well.
but the point is that all locks should have the same behavior in the 1-argument constructor case, and that is to block until this lock is obtained. The is the only way the user can use the lock in a generic way.
Absolutely. This is *extremely* important to keep in mind when discussing any kind of concept taxonomy.
I would consider this more an argument for eliminating 1-argument constructors entirely (except for scoped_lock, where its meaning is completely unambiguous): there doesn't seem to be a way to define them that is both consistent within the lock class and consistent across lock classes (e.g. I agree with Vladimir that for consistency within the try_lock class, it should be non-blocking; but as Christopher pointed out, for consistency across lock classes, it should be blocking). And, if you consider the larger case, which also includes read/write locks, single-argument constructors are even harder to define (do the read-lock or write-lock?; do they block or not?).
Refinements of a concept can only add restrictions, they cannot remove them.
True. But it's not hard to define the concepts in such a way that the lock classes can have different constructors: Lock concept defines all lock operations except constructors. TryLock concept refines Lock by adding try_* methods. TimedLock concept refines TryLock by adding timed_* methods. ScopedLock refines Lock by adding appropriate constructors. ScopedTryLock refines TryLock by adding appropriate constructors. ScopedTimedLock refines TimedLock by adding appropriate constructors. Mike