Boost logo

Boost :

From: Csaba Szepesvari (szepes_at_[hidden])
Date: 2000-09-14 14:03:14


William Kempf wrote:

> --- In boost_at_[hidden], Csaba Szepesvari <szepes_at_m...> wrote:
> > > You do not want the lock to do recursive locking. This is a
> trait of
> > > the mutex, not the lock. This interface is also less safe, since
> it
> > > removes any hope for compile time checking of the lock status in
> > > calls such as condition::wait(). I did, however, provide just
> such a
> > > lock called unsafe_lock<> that used the currently available
> interface
> > > to achieve this! So you really are unlikely to convince me here.
> > >
> >
> > You might have missed the point that I also used another type
> `alock' to
> > avoid this.
>
> No, I didn't. I explained it better in an early post.

Sure you did:)

> The lock
> class (alock or what ever name you choose to use) should not add
> recursive locking to a non-recursive mutex, and a recursive lock is
> pointless when you have a recursive mutex.

That's a separate issue, is not it? I was talking about exception safety
here..
First, you could use interfaces/compile-time checks to ensure that a
recursive lock will not work with a non-recursive mutex.

I do not agree that having a recursive lock that works with a recursive
mutex is pointless.
Consider

struct A
{
  boost::recursive_lock lock;
  A( boost::recursive_mutex& m ) : lock( m, notlocked ) {}; // no locking
here
  <various fns using lock>
};

The point is that A will clean up the locks upon destruction - I do not
see any problems here.

The alternate design is
struct A
{
  boost::mutex& m;
  A( boost::mutex& m ) {}; // this issues
  <fns usings auto-locks>
};
and if you are lucky then the following postulate will hold:
*** the syntactical scopes in the program coincide with the lock scopes
***
I think that the example of Levente was showing the point that this is not

always the case in a valid way.

> > Also:
> >
> > > > Having the two types of locks differing only in a template
> > > parameter and letting the
> > > > default be the one that disables the lock() method would also
> mean
> > > that people would
> > > > use the one exposing lock() only when they really need that one.
> > >
> > > That's what I said when I posted the unsafe_lock<> ;).
> > >
> >
> > I know, just forgot to refer that. Sorry.
> >
> > Recursive locks: With conditions, of course, you do not want
> recursive
> > locks. That's solved by having two types.
>
> You need only one type.

How did you derive that?? You also have unsafe_lock and lock..??
Why am I not allowed two types?

> Recursive locking is only useful for
> recursive function calls, in which case you'll be creating new locks
> on a recursive mutex. A recursive lock is redundant and violates the
> concept of a non-recursive mutex.

See above.

>
> > Having the lock() exposed on the interface of a lock type yields
> > exception safety provided that the lock knows how many times to
> unlock
> > (could be zero or one, better a bool, for a non-recursive lock).
>
> It should be a non-recursive lock, which is precisely how
> unsafe_lock<> was implemented.
>

Ok, then we are talking about the same things.

> > Another trait is whether the lock allows multiple calls to lock()
> that is
> > really a separate issue (both can be made exception safe).
>
> Multiple calls means recursive calls which, again, is a trait of the
> mutex not of the lock. They should not be allowed in unsafe_lock<>,
> resulting in an exception or some other error state.
>
> > what about lock<auto> and lock<manual> and auto would be the
> default so
> > lock<> would just work nicely.
> > Also, you could have lock_impl<xx> and typedef lock<auto> to lock.
>
> How is the implementation currently in the Win32 code failing you
> here? Why do you want to complicate things with a lock_impl<>?
>
> Seriously, I can't comprehend why we still have an issue here.
>

I have the same feelings:)

Summary
1) I don't see this template kind of thing too complicated
2) It's complexity is such that people will tend to use the simpler
(auto)lock - your goal and as well as mine
3) I don't like the name unsafe_lock.
4) having different types solves the compile-time check problem (no issue
with condition::wait, nor with non-recursive mutexes used with recursive
locks)
5) having a recursive mutex with a recursive lock is not evil, but on the
contrary, can be useful.
6) having a non-recursive lock with an explicit lock() is in.

I felt you were stressing the idea that a lexical scope must (ideally)
correspond to lock scope.
I don't see that this is justified.
I don't argue that this idea is wrong, but on the contrary, I think that
this is a very good idea.

I just don't want to let people write tricky codes like unsafe_lock and we
will push them doing that if the interface is too thin if the lexical
scope hypothesis does not work for them (for whatever reason).

What I'd like to see is to have a lock included in the interface that
allows for explicit locks.
Given that you have already agreeded on that the only thing that remains
to focus on is the actual interface design, e.g.,
if recursive locks or ruled out, template vs. non-template.

(I believed that having unsafe_lock in was still undecided, sorry of my
ignorance.)

- Csaba


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