Boost logo

Boost :

From: Howard Hinnant (hinnant_at_[hidden])
Date: 2004-07-07 13:48:45


I don't have strong feelings on the bool vs enum debate. But I do have
some comments below...

On Jul 7, 2004, at 10:31 AM, Michael Glassford wrote:

> Definitions
> -----------
> M: appropriate mutex type
>
> namespace lock_state {
> typedef enum
> {
> unlocked=0,
> locked=1
> } lock_state;
> } //namespace lock_state

ok.

> namespace read_write_lock_state {
> typedef enum
> {
> unlocked=0,
> read_locked=1,
> write_locked=2
> } read_write_lock_state;
> } //namespace read_write_lock_state

I'm not clear how these would be used. A read_lock is either locked or
not, same with write_lock. I'm not seeing a need, nor a desire for a
lock that can both read lock and write lock.

> namespace blocking_mode {
> typedef enum
> {
> non_blocking=0,
> blocking=1
> } blocking_mode;
> } //namespace blocking_mode

ok.

> ScopedLock / ScopedReadLock / ScopedWriteLock
> ---------------------------------------------
> lock(M) //always locking, blocking
> lock(M, lock_state) //blocking

ok.

> ScopedTryLock / ScopedTryReadLock / ScopedTryWriteLock
> ------------------------------------------------------
> try_lock(M) //always locking, BLOCKING
> try_lock(M, lock_state) //BLOCKING

ok.

> try_lock(M, lock_state, blocking_mode)
> try_lock(M, blocking_mode) //always locking

try_lock tl(M, unlocked, blocking);

What does this mean? The same as:

try_lock tl(M, unlocked); ?

Similarly is not try_lock(M, locked, blocking_mode) the same as
try_lock(M, blocking_mode)? If I'm interpreting this correctly, how
about the following reduced list to eliminate redundancy:

     try_lock(M) //always locking, BLOCKING
     try_lock(M, lock_state) //BLOCKING (if attempting to lock)

     try_lock(M, blocking_mode) //always (attempt) locking

Btw, this would require enums over bool.

> 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

Note that the addition of the try_lock stuff to ScopedTimedLock is a
change. I don't disagree with that change. Just hilighting it. It is
essentially alternative syntax for a timed_lock specified with a 0
delta time.

Speaking of which, I've never been happy with "t" in the
ScopedTimedLock docs. I've always felt it was ambiguous. Does t
represent an absolute time, or a change in time? Both interpretations
are useful. In the Metrowerks::threads lib I have:

     scoped_timed_lock(mutex_type& m, const universal_time& unv_time);
     scoped_timed_lock(mutex_type& m, const elapsed_time& elps_time);

Where universal_time and elapsed_time are simplistic structs (like the
boost time), but represent absolute and delta times respectively. They
can also be added and subtracted as makes sense (e.g. you can add a
universal_time and an elapsed_time, or two elapsed_time's, but you
can't add two universal_time's). I took the Posix route and defined
universal_time as the number of seconds and nanoseconds since midnight
Jan. 1, 1970, UTC. The universal_time default constructor returns the
current time.

So how about:

     timed_lock(M) //always locking, blocking
     timed_lock(M, lock_state) //blocking

     timed_lock(M, blocking_mode) //always locking

     timed_lock(M, universal_time u) //always locking, blocking until u
     timed_lock(M, elapsed_time t) //always locking, blocking for
elapsed time t

?

-Howard


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