$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: Michael Glassford (glassfordm_at_[hidden])
Date: 2004-07-07 09:31:42
Peter Dimov wrote:
> Michael Glassford wrote:
> 
>>Peter Dimov wrote:
>>
>>>Howard Hinnant wrote:
>>>
>>>[ read/write mutexes and locks ]
>>>
>>>Seems very good to me. Also demonstrates a better lock taxonomy
>>
>>Better compared to what? The current read/write lock taxonomy? One of
>>the many suggestions in this discussion?
> 
> 
> Better compared to the current non-read-write lock taxonomy.
> 
> 
>>>Lock
>>>
>>>    Lock( Mutex&, bool = true );
>>>    void lock();
>>>    void unlock();
>>>    bool locked() const;
>>>    operator int bool_type::* () const;
>>>
>>>TryLock: Lock
>>>
>>>    +bool try_lock();
>>>
>>>TimedLock: TryLock
>>>
>>>    +bool timed_lock( xtime const & );
>>
>>The point being that TryLock is a refinement of Lock, and TimedLock
>>is a refinement of TryLock? If so, I agree that's better than TryLock
>>and TimedLock both refining Lock. There are still the constructor
>>issues to deal with in such a lock taxonomy, however.
> 
> 
> I don't see any. There is one constructor, with the same behavior.
OK. I hadn't realized that you meant there to be literally only one 
constructor; I do now.
>>The main one: how do you
>>define destructors that are consistent within a lock concept and also
>>consistent between concepts.
> 
> 
> ~Lock { if( locked() ) unlock(); }
> 
> however it looks like you meant 'constructor'.
Sorry, I did mean constructor.
>>E.g., on the one hand it seems that a
>>one-parameter constructor should do the same thing in all lock
>>types--so
>>it would have to block; on the other hand, it seems that TryLock
>>constructors should not block unless instructed to do otherwise.
> 
> 
> I meant what I said. There is a single constructor. Its behavior is
> consistent across all lock concepts (it it weren't, a TryLock would not be a
> Lock). A mutex exposes a single lock type, which is as refined as possible.
OK, that makes sense and is consistent (which I like). 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