Boost logo

Boost :

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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk