From: Matt Hurd (matt.hurd_at_[hidden])
Date: 2004-07-15 18:19:24
On Thu, 15 Jul 2004 16:03:36 +0300, Peter Dimov <pdimov_at_[hidden]> wrote:
> Matt Hurd wrote:
> > Yes, that is the classic solution but it never strikes me as quite
> > what I need.
> > I've been struggling to find a cute solution I'm happy with. Mainly
> > because I also typically want to expose the foo1_impl() for the cases
> > when I wish to lock externally for multiple operations.
> Andrei Alexandrescu's suggestion is to make foo1_impl take a lock:
> void foo1()
> scoped_lock<> lock(mx_);
> foo1( lock );
> void foo1( scoped_lock<> & l )
> assert( l.locked() );
> assert( l.mutex() == &mx_ ); // or not, to allow ext. sync
> // do things, incl. foo2( l );
> This doesn't solve the boilerplate problem, though. Maybe something like
> void foo1( scoped_lock<> * pl = 0 )
> assert( pl == 0 || pl->locked() );
> scoped_lock<> internal_lock( mx_, pl == 0 );
> if( pl == 0 ) pl = &internal_lock;
> // do things, incl. foo2( pl );
> where the boilerplate can be hidden in a class.
Been thinking a little about it. I see some pros and cons to this approach.
Pro: discrimination at run-time to enable different states to support
different locking strategies.
Pro: doesn't mess up methods that require bool template parameterisation
Con: run-time overhead
(or needing better compilers for global optimization than we
Con: defaults on parameters messes up the interface if you want to
have other parameters that are optional too.
Con: requires a lock abstraction when you might be able to get away
without one for your use case in the state your are dealing with.
That is, don't need a lock, don't require one.
The case for not requiring a lock should have zero cost at runtime.
Stroustrup's don't pay for what you don't use principle. The caveat
is that with modern compile time programming this should probably
translate to something like, "with most modern compilers' optimization
capabilities... don't pay...".
Maybe a hybrid / dual approach is better.
I am still trying to see this in a holistic sense were
blocking/polling and non-threaded/threaded can be parameterized as
well as allowing dual use of the objects.
Would be nice to consider this interface w.r.t. other resource
acquisition, such as file and socket i/o as the blocking, try, timed
argument is still relevant to these resources as well.
Along these lines perhaps locking can be considered one of many
potential run-time preconditions or predicates that you may want to
pay for a single evaluation/use sometimes to minimize the cost of
state transitions. Locking is just one very common example.
On the flip side, perhaps we should forget about it or give up ;-) ,
just layer a simple api on top of the common posix, win32, dce
abstractions, like ace does and worry about C++ niceness later. I'd
rather get it nice though as there are other libraries that do this
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk