Boost logo

Boost :

From: Matt Hurd (matt.hurd_at_[hidden])
Date: 2004-07-16 20:20:59


On Fri, 16 Jul 2004 13:54:32 -0400, Michael Glassford
<glassfordm_at_[hidden]> wrote:
> In an attempt to reconcile the different preferences and ideas expressed
> in this thread, here's a thought experiment for mutex & lock
> unification. What if the mutex and lock classes were policy-based,
> allowing users to choose the interface they want and supplying a typedef
> or two for the "most common" or "approved" variations?
>
> Example below (note that I haven't tried to implement multiple policies
> elegantly). Hopefully it could be expanded to include recursive,
> checked, read/write, etc.
>

<snip>

> //Example typedefs:
>
> typedef mutex_type<
> blocking_mutex_policy,
> try_mutex_policy,
> fast_timed_mutex_policy
> >
> mutex;
>
> typedef blocking_mutex_type<
> blocking_mutex_policy,
> null_policy,
> null_policy
> >
> mutex;
>
> typedef try_mutex_type<
> try_mutex_policy,
> null_policy,
> null_policy,
> >
> mutex;
>
> typedef timed_mutex_type<
> timed_mutex_policy,
> null_policy,
> null_policy,
> >
> mutex;
>
<snip>
> //Example typedefs:
>
> typedef lock_type<
> blocking_lock_policy,
> try_lock_policy,
> timed_lock_policy
> >
> lock;
>
> typedef lock_type<
> blocking_lock_policy,
> null_policy,
> null_policy
> >
> blocking_lock;
>
> typedef lock_type<
> try_lock_policy,
> null_policy,
> null_policy>
> try_lock;
>
> typedef lock_type<
> timed_lock_policy,
> null_policy,
> null_policy
> >
> timed_lock;
>

I think this is thinking along the right track though I'm not fond of
your interface above, but it is a good start to the thinking.

I've been reading over some of the old boost thread threads and I
think I now see why Bill Kempf is now away from boost::thread. The
best spin is, I think, he gave up on consensus.

It it interesting the old ground we are covering, some of the thinking
back then was perhaps a little better then. Some of the current ideas
seem a little better too.

I do like David Held's thinking, perhaps because it is similar to mine
;-), in these mails:
    http://aspn.activestate.com/ASPN/Mail/Message/boost/1213138
    http://aspn.activestate.com/ASPN/Mail/Message/boost/1207304

Bill Kempf was concerned about providing as safe as possible semantics
for locking.
He saw the need for lock transfers especially for Bjarne's auto
locking proxy idiom.
One way of doing this was to expose lock and unlock on a lock, but he
felt exposing the same on the mutex was safer yet still troubling.
Bill related transfer semantics to auto_ptr and saw the shared_ptr
approach as problematic.

Others are of the opinion that lock and unlock is fine and catering
threading newbies should not prevent them from the low level tools
that makes their life fun ;-)

I side with Bill, on balance, I think on this. I see public a lock
and unlock as the equivalent of a threading "goto".

However, I'm not so sure about his shared pointer reluctance at one
level. His argument was that a shared_pointer interface requirements
are a lot different to an interface for a lock with move/transfer
semantics, which is true. He also argued that sharing a lock made no
sense and was dangerous. This is kind of true, but we do share a
mutex with a shareable mutex (the one i keep calling a shareable mutex
and the world calls a read write mutex).

A non-shareable mutex in effect would have a count of zero or one
(true or false) and ownership transfer would be the correct interface.
 Careful consideration must go to thinking about such situations as :
    do_something( lock_object );
w.r.t. to transfer. Perhaps
    lock_object = do_something( lock_object );
covers the case, but I can see the danger already...
    
There are grounds for concern over the implementation delivery of
shared / transfer implementation as it should either rely on
no-locking, atomic primitives or locking primitives below the normal
locking to avoid the chicken and the egg of locking a count.

I would like to see David Held's RIIA mechanism, mixed with Michael's
policy approach to deliver a solution that could also be consistent
with the resource acquisition requirements of socket and file i/o.
Timer interaction, especially because or try_lock, where the timer is
a resource should perhaps be covered too.

The mutex taxonomy I have in mind would be:
    1. null_mutex
            elided ops, atomic ops with interlocking
    2. simple_mutex
            basic os mutex / critical section
            recursive on windows, non-recursive on posix
    3. recursive_mutex
            recursive always
    4. shareable_mutex
            supports exclusive and shared access
            reflects os primitives where available
            ( what does this mean with recursiveness???)
    5. upgradeable_shareable_mutex
            adds upgradeable read lock equivalent

yeah, maybe not the best names

- a lock is a resource acquisition on a mutex.
- avoid lock and unlock methods if possible via move/transfer semantics
- consider a read lock as a shared_lock, lots of owners.

run out of time, gotta go bike riding with the kiddies...

$AUD 0.02

Matt Hurd.


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