
Michael Glassford wrote:
What about the following as an alternative? I retain the hierarchy (a TryLock is a Lock, a TimedLock is a TryLock) and resolve the conflict
(of
consistency within a concept and consistency across concepts) by the principle that a constructor always blocks unless you specifically tell it not to:
Definitions ----------- M: appropriate mutex type
namespace lock_state { typedef enum { unlocked=0, locked=1 } lock_state; } //namespace lock_state
namespace read_write_lock_state { typedef enum { unlocked=0, read_locked=1, write_locked=2 } read_write_lock_state; } //namespace read_write_lock_state
namespace blocking_mode { typedef enum { non_blocking=0, blocking=1 } blocking_mode; } //namespace blocking_mode
ScopedLock / ScopedReadLock / ScopedWriteLock --------------------------------------------- lock(M) //always locking, blocking lock(M, lock_state) //blocking
ScopedTryLock / ScopedTryReadLock / ScopedTryWriteLock ------------------------------------------------------ try_lock(M) //always locking, BLOCKING try_lock(M, lock_state) //BLOCKING
try_lock(M, lock_state, blocking_mode) try_lock(M, blocking_mode) //always locking
ScopedTimedLock / ScopedTimedReadLock / ScopedTimedWriteLock ------------------------------------------------------------ timed_lock(M) //always locking, blocking timed_lock(M, lock_state) //blocking
timed_lock(M, lock_state, blocking_mode) timed_lock(M, blocking_mode) //always locking
timed_lock(M, t) //always locking, blocking for time t
This is certainly possible, but I don't see what the additional complexity buys us. TryLock l( m, false ); if( l.try_lock() ) { } looks acceptable to me. TryLock l( m, non_blocking ); if( l.locked() ) { } doesn't seem much of an improvement.