
On Fri, 16 Jul 2004 13:54:32 -0400, Michael Glassford <glassfordm@hotmail.com> 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.