|
Boost : |
From: Csaba Szepesvari (szepes_at_[hidden])
Date: 2000-09-14 09:33:53
Levente Farkas wrote:
> hi,
> I find an example where lock and unlock can be useful.
<..>
[You're going to think that Hungarian (Mindmaker) people have teamed up in this
subject;) Anyway, I feel I have to say something. Hope that it will be useful.]
I agree with Levente on that having a lock() exposed would be useful (as shown by
the example he provided).
However, having a lock on the mutex is probably not the best way because of
exception safety considerations as people have already noted here.
However, having another lock class, say `alock' [not a very good name, I know ;-) -
we could also use templates with different parameters and having only one lock
class] with an explicit lock function, but with one that would count the calls to
lock() itself and in the destructor unlocking the mutex the appropriate number of
times - this class would resolve *some* of the safety considerations raised here
earlier.
So Levente's example would look like:
{
boost::alock lock(m); // this already locks m
for (int i = a.get(); i < 10; a.next())
{
<some code part 1>
lock.unlock();
f();
lock.lock();
<some code part 2>
}
// lock's destructor releases the mutex m the app. no. of times
}
and if an exception is thrown in <some code part 1> or <some code part 2> then the
lock unlocks m the appropriate number of times.
Ok, you can try to call unlock more no. of times that you called lock - but is not
this the same with `delete'?? Life is dangerous.. .. or do not use C++ ;) Maybe,
unlock should not do anything when called a larger number of times than lock? I
guess I would not like this I don't know why, just a feeling - I prefer throwing an
exception (it will turn out soon - hopefully- that there is a problem with the code)
Also, having two different types, one with lock() exposed, another one without it,
and having condition only accept the one without the lock() method exposed - the
compile time guarantee needed for condition::wait() would be ok, also.
As to the deadlocks, you can cause deadlocks easily even using autolocks, consider
the textbook example:
void f()
{
boost::lock l1(m1);
boost::lock l2(m2);
<code1>
}
void g()
{
boost::lock l1(m2);
boost::lock l2(m1);
<code2>
}
I am sure we can all agree on that there is no way to prevent people of misusing
tools.. (of course, we knew this).
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.
Cheers,
Csaba
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk