Boost logo

Boost :

From: Michael Glassford (glassfordm_at_[hidden])
Date: 2004-07-16 22:38:43


Matt Hurd wrote:

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

Do you mean having three template parameters? I mentioned that that was
just for the sake of example. If you mean something else, I'm not sure what.

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

This occurred to me during this massive threading thread. It seems that
no two people agree on what a threading library should look like (e.g.
some people want one mutex class and one lock class; others want three
mutex classes and three lock classes with no overlap; others want three
of each, with each being a superset of the last; others like things the
way they are now; etc.). I thought perhaps that well designed
policy-based classes could give most people what they want without
making everyone else have it too.

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

Yes, many of the same discussions seem to get rehashed, don't they? Much
like they do with smart pointers, oddly enough.

> 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

I read things the opposite way. At the very beginning he wanted no lock
an unlock methods on the lock, but changed his mind or at least conceded
the argument; however, he thought (and I agree) that lock and unlock
methods on the mutex were dangerous. Did you mis-type, or could you give
references?

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

I agree that sharing a lock makes no sense; explicit transfer (not
sharing) of a locks seems to make sense in some circumstances, though.

I think Bill came to the conclusion that transferable locks were
something he should do, and that most/all of the people participating in
the discussion agreed.

> 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'm not sure I understand what you're getting at. To make sure we're
talking about the same thing:

1) I'm not talking about transfer of locks between threads.
2) I am talking about transferring locks from one scope to another scope
(e.g. out of a function) within the context of a single thread.
3) This is essentially move construction or move assignment (that is,
the internal state of one lock--e.g. the mutex reference and lock
state--is copied into another lock, then the first lock clears its state
so that it doesn't try to unlock the mutex or whatever). It's a transfer
of ownership.
4) I'm not talking about transfer = lock promotion or demotion. Though
the syntax is the same, it's a different operation (ownership is
transferred, but the lock type is changed as well). That's not to say
that I disagree with that syntax for promotion or demotion, just that
that's not what I mean when I talk about lock transfer.

> 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

This is a good idea.

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

Mike


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