|
Boost : |
From: williamkempf_at_[hidden]
Date: 2001-07-17 11:37:11
Jeremy Siek asked me several questions in e-mail about the design and
usage of Boost.Threads. I think the responses are pertinent for the
group, so I'm responding to them here.
>From: Jeremy Siek <jsiek_at_[hidden]>
>To: <williamkempf_at_[hidden]>
>Subject: monitor pattern
>Date: Tue, 17 Jul 2001 10:32:38 -0400 (EDT)
>
>Hi Bill,
>
>I just came across a small snag in using the "monitor" pattern.
>
>class X : public mutex, public condition {
>public:
> void foo() const {
> lock lk(*this); // problem, *this is const but lock constructor
> // takes non-const
> }
>};
>
>one solution is writing this instead:
>
>class X {
> mutable mutex mtx;
>public:
> void foo() const {
> lock lk(mtx);
> }
>};
>
>Ciao,
>Jeremy
The Boost.Threads documentation mentions the monitor pattern only in
passing and references the reader to POSA2 for a formal definition.
On Pg. 409 in POSA2 the "mutable" version is precisely that which is
recommended for usage. I'll add a FAQ about this question as I
expect others to raise it as well, but the "mutable" trick is the
appropriate usage here (that or use a Read/Write lock instead of a
traditional mutex, that is, once Boost.Threads has one).
>PS. Do you plan on adding reader/writer locks anytime soon? You
might be
>able to get Terekhov to provide the implementation.
Depends on your definition of soon. I want to formally submit
Boost.Threads before adding this type, with the idea being that the
current implementation provides a "complete but minimal" library.
After acceptance I'll work on other extensions. Those I'm interested
in are Read/Write locks, Barriers, Cleanup stacks and possibly Once
methods.
>From: Jeremy Siek <jsiek_at_[hidden]>
>To: <williamkempf_at_[hidden]>
>Subject: mutex noncopyable
>Date: Tue, 17 Jul 2001 10:46:40 -0400 (EDT)
>
>Hi Bill,
>
>Another glitch in the "monitor" pattern. Since mutex is noncopyable,
>then doing either this:
>
>class X : private mutex { ... }
>
>or this:
>
>class X {
> mutex mtx;
>};
>
>causes X to also be noncopyable, which in many cases is unacceptable.
>Therefore, currently the implementor of X has to do this:
>
>class X {
> mutex* mtx;
> X() : mtx(new mutex()) { }
> ~X() { delete mtx; }
>};
>
>which is a pain.
And simply wrong ;). A mutex *IS* a noncopyable concept. If you
remember, we discussed this early on in the design. Allowing a mutex
to be copyable just leads to incorrect code, similar to what you have
with your work around above. Why incorrect? Because the
implementation you have above results in two distinct sets of data
being protected by a single mutex. If CopyA locks the mutex then
CopyB is locked as well. This can lead to hard to diagnose deadlocks.
However, just because the mutex isn't copyable doesn't mean that an
object that contains a mutex must be noncopyable. It just means you
can't rely on the compiler supplied copy c-tor and assignment
operator. This turns out to be a good thing any way, since such
operations should lock both mutexes before doing the copy, which is
something the compiler supplied versions aren't going to do any way.
>So my question is this: is there any way we can get mutex to be
copyable?
No. At least not while maintaining correct MT behavior. I'll add
this one to the FAQ as well, along with appropriate code examples
addressing both questions.
>Cheers,
>Jeremy
Bill Kempf
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk