$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: William Kempf (sirwillard_at_[hidden])
Date: 2000-09-08 11:24:15
--- In boost_at_[hidden], Levente Farkas <lfarkas_at_m...> wrote:
> 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.
Debatable.  Also irrelevant if you wrap the concept, as I did in 
another post with the "unsafe_lock".
> > 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.
It's a good thing that most users won't use it.  If a user absolutely 
must have overlapping locks, he will use it.  As for calling the 
private functions... uhmm... not unless you hack the code.  You don't 
have access to the private functions.  That's the whole point here.
  
> > > > 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();
and a.bar();
You've gone back to the "right" interface here.  The point is, my 
experience tells me that if you allow both interfaces programmers use 
the unsafe interface when they shouldn't and wind up with the problem 
I illustrated.
> > 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.
Recursivity has nothing to do with this.  foo() could have been 
called in one thread and bar() in another to get the same results.
 
> > 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.
Which example?  I'm a little lost here since we've both posted 
several examples.
  
> > 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!!!
Yes, it is.  I have to use code written by those programmers.  I have 
to maintain code written by them.  I have to help them figure out why 
they're deadlocking.  Why?  Because they are my colleagues working on 
a large project.  We don't work in a vacuum.
> 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)!
It's already prevented, IMHO.  Firstly, the lock/unlock that exists 
in the mutex is private so you don't have access to them even if you 
subclass.  Secondly, there's not a virtual destructor so subclassing 
is strongly discouraged.  So, reasonable misuse is prevented.  Yes, 
you can still misuse things, but only by bending over backward, which 
is then your problem, not mine.
  
> > 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.
No, I can't see a subclass example, because you still have no access 
to lock/unlock.
  
> > 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.
No, it's not a matter of putting my back up.  I simply don't agree 
with what you said, and I gave cogent reasons why not.
> the above was not
> my opinion and I don't vote for this.
Then I'm very confused.  You posted someone else's opinion?  Well 
then, I disagree with them, not with you.
> 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.
I don't agree.  Most reasonable programmers would not resort to using 
platform specific types exclusively just because our library didn't 
include them.  This is especially true if the library were to someday 
be part of the language standard.
> > 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.
On the event, yes.  But that's simply a wait operation, not a 
unlock/wait/lock operation.  Apples to oranges, and anyone that is 
introduced to CVs should see this.
  
> > > 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).
You're putting words into their mouths and making assumptions.  
Again, I'm a Windows programmer exclusively.  I've never touched 
pthreads.  I didn't react this way or think this way when I was 
introduced to CVs and portable thread libraries.  Personally, I doubt 
that most people would react any differently than I did.
  
> > 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.
Have to?  I don't think so.  If we do, than why are we stopping 
there?  Why not gates as well?  I'm sure there are numerous other 
synch objects in use else where, so we need to include all of them.
No, if they are trivial to implement and don't really gain you 
anything over the other synch objects I don't think they warrant 
consideration.
> > 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.
Why?  What's gained/lost/different?  Again, the mutex in my 
implementation is as fast (or at least close), has all the 
functionality, plus it allows timed locks, portable try locks (the 
critical section only has try locks on NT) and can be shared between 
processes with minor alteration of the interface (that functionality 
is still being discussed).
> > 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.
I know that.  I wasn't trying to compare Win32 to posix, only list 
the Win32 concepts that aren't currently in the Boost 
documentation/concept code.
 
> > 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.
Then you should prefer the current interface as there are fewer 
functions and no duplication of functionality while making it much 
harder to write buggy code.  Your proposed change to the interface 
violates all of these additional criteria.
Bill Kempf