Boost logo

Boost :

From: Levente Farkas (lfarkas_at_[hidden])
Date: 2000-09-08 10:15:55


William Kempf wrote:
> > that's not a good example, since on the interface THERE IS a
> function
> > for const char*, but in the mutex there si no lock!
>
> Oh yes, there is a lock, it's just not a function.

yes and the code loose it's simplicity and clarity.
 
> > choice 2. use the muteces luck/unlock function but in this case the
> wait
> > or any other place where the compile time check is not
> possible
> > use runtime or don't perform check. in this case the
> programmer
> > have to be more careful about design (thread,
> exception...),
> > BUT he's got chance to do so!!! and it's a big difference
> from
> > current situation.
>
> No, it's not. He can still do so with the current interface.

yes and the code loose it's simplicity and clarity.
 
> In this case, the safe way loses no performance (well, maybe a very
> slight performance depending on how well the compiler optimizes
> things) and no functionality. That last part seems to be what you're
> forgetting. I've shown how you do explicit lock/unlock using the
> class approach, and pointed out how it's going to be very rare that
> you'll want to do so any way.

we just loose simplicity and clarity.

> Sorry, but I'm not willing to sacrifice safety here, since there's no
> functionality lost.

my math teacher use to said that you can add two number by
a + b
and
arcsin(sin(a)) + ln(exp(b))
but the first is more elegant:-)
(ps. don't start to discuss that the above is not realy the same thing:-)
 
> They don't NEED to. You've got to remember that. If explicit
> lock/unlock is required than you create the lock on the heap. No
> functionality lost, no performance lost.

yes and the code loose it's simplicity and clarity.
and most user won't use it, what's more I can cheet and call the private
function if I realy want it, but that's not what I want.
 
> > > The comparison is apples to oranges. Fail to open the stream and
> you
> > > get obvious runtime errors. Fail to close the stream and it'll be
> > > closed for you at the time of destruction. The impact is small
> and
> > > obvious. Not so with mutex locks. Fail to lock a mutex and call
> > > condition::wait() and you've got undefined behavior (with a more
> > > complex requirement on this we could have this result in a runtime
> > > error, but this is dangerous because of my next point). Fail to
> > > unlock the mutex and you get a runtime error... a deadlock! This
> >
> > the destuctor of a mutex can always unlock it (if it's locked).
>
> class A
> {
> mutex mx;
> public:
> void foo()
> {
> mx.lock();
> }
> void bar()
> {
> mx.lock();
> }
> };
>
> A a;
> a.foo();
> a.bar(); // Foo-barred indeed!

class A
{
  mutex mx;
public:
  void foo()
  {
    mutex::lock lock(mx);
    bar();
  }
  void bar()
  {
    mutex::lock lock(mx);
  }
};

A a;
a.foo();
 
> The problem domains are not the same between a stream and a mutex.
> If mx had been a stream and we'd called open instead of lock we'd
> have no real problem here. The second call to open could have either
> failed or closed the old file and the destructor would insure the
> file was eventually closed. With the mutex, the same programming
> error has instead lead to deadlock. Possibly disastrous deadlock.

if the mutex is not recursive yes (although I vote against it many times
in this list), but if it's not recursive, the above code also suck.

> Maybe deadlock that only rarely occurs. Likely deadlock that's very
> difficult to debug and correct. No, it's apples and oranges and I
> simply won't live with the danger. I think that anyone that's done
> extensive threaded programming would agree with me.

I don't, just see the above simple example.
 
> > > sort of runtime error is extremely difficult to diagnose and
> correct
> > > because of the sheer nature of threads. The cost of making
> mistakes
> > > is high enough that we MUST attempt to prevent as many mistakes as
> > > possible at COMPILE time, even if this means corner cases become
> > > slightly more difficult to deal with.
> >
> > yes, and we can do so with auto-lock for everybody who use it, and
> the
> > others take the risk.
>
> I've seen so many libraries designed this way. Even with good
> documentation on the dangers I've found that most people who program
> using these libraries still use the explicit lock/unlock functions
> when they should be using an auto-lock, and I've seen many a deadlock
> occur because of this. My experience here is going to make me very
> hard headed about this. I will argue with you until you're sick of
> me about this one. I'm not in favor of exposing lock/unlock on the
> mutex itself.

BUT THIS IS NOT YOUR PROBLEM!!!
what if I make a subclass of mutex which have a lock and unlock function ?
do you wanna prevent this too ? you can't (if I can lock and unlock somehow)!
 
> > > > > We don't have to work around the problem here, we just have
> to use
> > > > > the lock in a different manner. Portable, relatively safe and
> > > > > strongly illustrates the dangers when used.
> > > >
> > > > I think it has nothing to do with portable. and the mt stuff is
> > > always
> > > > dangerous nad hard to debug and ...
> > >
> > > Which is precisely why a good mt interface will go out of its way
> to
> > > catch mistakes at compile time!
> >
> > yes in cases where possible.
>
> And it's very much possible here. Why are you fighting me on that
> point?

you can't see the above subclass example.
just beacuse I'm belive I'm right.
 
> Uhmm... I'm a Windows programmer. I've never used the pthread
> library (though I've studied it for academic reasons). I disagree
> with you totally. They may have never seen a CV before, but a simple
> explanation and a quick example and I bet the vast majority of them
> will have no problems understanding them or fail to see their power.
> Most will probably even understand how they are superior to the
> Windows event, which is the closest analog available to them. Heck,
> most of them have probably coded a CV themselves!

it seems to me that you realy just wanna argue with me. the above was not
my opinion and I don't vote for this. I just simple state the the
higher level part of a thread library would have to support all (most)
platform's primitives if we'd like to be excepted by most people.
actualy mutex and cv would be enough for me and monotor, rw-lock and a
few other at higher level.
 
> As for not understanding why you need a mutex for a condition...
> that's probably the most obvious thing to grasp after a condition is
> described. The atomic operation of unlock/wait/lock is an obvious
> advantage over Win32 events.

operation on event also atomic.
 
> > so I suppose generally it's not a good idea to go too far from the
> current
> > patterns, neither from win23 nor from posix. we have to support
> primitives
> > of both "platform". probably the win32 primitives will slower on
> posix and
> > vice versa. eg support for WaitForMultipleObject is a requirement
> from the
> > win32 word and they can argue with it, while the CV (with wait
> which requires
> > a mutex) is requirement form posix word.
>
> Sorry, I disagree here. WFMO is a poor hack to work around the lack
> of condition variables. The only case in which it's really useful is
> when waiting on multiple events, which is the same as waiting on
> multiple predicates tied to a single CV, or when waiting on multiple
> threads to end, which can be done in so many different ways that it's
> just a convenience function there.

again, I agree with it, but those who use it used to use it and if they
got a library whithout it, they will say it's just a subset (without
thinkink, cause they think in another way).
 
> Win32 events really serve little purpose when you have CVs. They are
> also trivial to implement on your own. So, I don't think they
> warrant consideration.

that's why we have to implement it.
 
> Critical sections are just faster mutexes (as well as not being
> kernel objects, but that means a lack of functionality which isn't a
> reason to include them). Since I've shown a mutex written for Win32
> that's (nearly) as fast as a critical section, there's no reason to
> include it.

I don't want to include it, but maybe a typedef for our mutex as
critical section would help in a first place, later can be deleted.
 
> We've got analogs to the Win32 semaphore and mutex. The only Win32
> concepts we're really missing at this point and time are TLS and
> MsgWait. TLS will be added in due course. MsgWait isn't very

there is tls in posix too.

> My goal is safety, flexibility, attention to C++ constructs,
> standardization (it would be nice to eventual make it into the
> language standard) and speed. I think we're well on the way there.
> I don't see the interfaces as being "usable only by experts", and in
> fact think we've done the opposite... made advanced concepts easier
> to use (correctly!) and understand by beginners.

my other goal is to be clear, simple and small as my belive is if a code is
smaller (where the smaller is not depend on the name of the variables and so)
is better since it's more simple easier to read and can contain less bug.

 -- Levente
 "The only thing worse than not knowing the truth is
  ruining the bliss of ignorance."


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