Boost logo

Boost :

From: Michael Glassford (glassfordm_at_[hidden])
Date: 2004-07-07 23:22:37


Howard Hinnant wrote:
> 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.

Earlier in this discussion I gave a lot of examples of cases where
separate read_lock and write_lock classes had problems. I'll have to go
back over my examples with more recent discussion in mind to see if the
problems have been addressed before I can comment on this.

>> 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); ?

Yes. A while back I was working on a way to eliminate such degenerate
cases that using structs instead of enums to select an appropriate
constructor at compile time, but it had the disadvantage of being unable
to select the appropriate behavior at run time, so I shelved the idea.

> 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

I wouldn't object to that. I think the reason I hadn't made this
simplification already is that I originally thought try_lock(M,
lockstate) should not block, but now that I've changed my mind about
that it makes sense.

> 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.

Yes, it's a change; thanks for highlighting it. I think that either
TimedLock should refine TryLock, or else that Lock, TryLock, and
TimedLock should be completely separate (as Vladimir suggested), none
being refinements of any of the others.

> 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

Yes, something needs to be done about time. There was a discussion of it
recently by people who care about time issues, but I wasn't able to
devote enough time to it then, and haven't gotten back to it. Perhaps we
can address that issue later? The issues we're already dealing with
(lock concept taxonomies, constructors, read/write locks, promotion) are
complex enough for me already.

Mike


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