|
Boost : |
From: williamkempf_at_[hidden]
Date: 2001-07-02 07:58:10
--- In boost_at_y..., Ross Smith <ross.s_at_i...> wrote:
> Apologies for taking so long to get back to you on this; I've been
a bit
> busy. (I recently installed a multiple-boot system on my
workstation,
> with the result that I spent most of last week playing musical
chairs
> with various bits of hardware and software, trying to get Linux and
> Windows to play nice together.)
>
> williamkempf_at_h... wrote:
> >
> > --- In boost_at_y..., Ross Smith <ross.s_at_i...> wrote:
> >
> > > It also seems to be following the pthreads architecture too
closely
> > for
> > > my taste. It doesn't really "feel" like a designed-from-scratch
C++
> > > library to me -- more like a thin OO wrapper around the pthreads
> > API,
> > > and an attempt to emulate it on Windows. (I'm thinking in
> > particular of
> > > condition variables, a pthread-specific concept that I don't
think
> > > belongs in a generic threading library.)
> >
> > This is ironic. I'm the main developer on this (though I've
gotten a
> > lot of input from others) and I'm a Win32 programmer with little
> > experience with pthreads. The only thing in the library that is
> > pthread-like instead of Win32-like is the condition variables, and
> > this happens to be a major lacking in the Win32 API. I don't
know of
> > any serious MT programmers on the Win32 platform that haven't
rolled
> > their own CV concepts because of this. The CV concept is
_required_
> > to use a monitor pattern, which is one of the most flexible and
easy
> > to use synchronization concept in OO programs.
>
> Probably part of the problem for me is that I've had to work out
> techniques for cross-platform multithreading myself, with no contact
> with anyone else working on the same sort of thing, so I've probably
> reinvented several wheels and ended up with different concepts and
> terminology. I have no idea what a "monitor pattern" is, for
example.
Look it up :). The Boost.Threads library describes it and gives the
classic example, a bounded buffer that's read from and written to by
different threads, implemented using the Boost.Threads library.
> I've always found condition variables very complicated and
difficult to
> understand. Whenever I use them I always have trouble working out
how to
> make them do what I want. I find the Windows equivalent, events, to
be
> much more intuitive and easier to follow.
Events are much more error prone and can't be used in a monitor
pattern. The reason for this is that they don't work in conjunction
with an external mutex. A condition variable does. You lock the
mutex first, then possibly do some work with shared data, then wait
on the CV. The wait operation first unlocks the external mutex, then
blocks until the CV is signaled, then re-locks the mutex. This
insures that you retain exclusive access to shared data before and
after a wait, but not during. You can't do the same thing with an
event with out causing race conditions.
In any event, your unfamiliarity with how to use CVs is not a good
reason to dislike the library or for us to remove them. The CV
concept is essential to most MT patterns and it was simply a mistake
that Win32 never included one (that's coming from a Win32 programmer
with no POSIX threads experience, remember). In fact, every Win32
programmer roles their own as soon as they learn what one is. The
problem is, rolling your own is tricky and usually isn't done
correctly.
> > In fact, I'd expect more people to accuse the design of being too
> > Win32 biased. For instance, the design of the Semaphore includes
a
> > max setting and methods to increase the semaphore value by
variable
> > amounts instead of one at a time. Another example is the design
of
> > the thread class itself, which allows for multiple join() calls
and
> > has no concept of detach(). I could continue with this list, but
I
> > think you get my point.
>
> Well, no, not really. The whole "join()/detach()" concept is pthread
> specific.
No, it isn't. The terminology is POSIX terminology, though we use
slightly different meanings here. However, Win32 still has these
concepts under different names. A join() is just a Wait*() operation
on the thread handle. A detach() is just a CloseHandle() operation,
though Win32 HANDLES are ref-counted changing this slightly from
POSIX, but possibly not from the meaning in Boost.Threads.
> > > (When I have a bit more spare time, I'll polish up my own thread
> > library
> > > and post it somewhere for comparison.)
> >
> > I'd be interested in seeing this, but it may be better for you to
> > point out specific things in the current implementation you'd do
> > different.
>
> Looking back at the path the design has been taking recently, I
suspect
> we've diverged too far. I can't understand the liking so many people
> have for the "thread_ref" concept. Non-copyable objects, with smart
> pointers when necessary, are the standard C++ idiom for this sort of
> thing; why treat threads differently? I'm afraid I Just Don't Get
It.
Why are Win32 handles ref-counted concepts, with DuplicateHandle?
_That_ is why people feel more natural with a ref-counted design.
That said, I've been swayed since the initial design that this
probably isn't a good thing. I guess this particular argument isn't
dead yet. I just find it surprising that you prefer noncopyable
types when Win32 types are both copyable AND ref-counted (with the
ability of the user to choose which type of copy to do).
> Anyway, in case anybody's interested, the current state of my
threads
> library can be found at:
> http://storm.net.nz/~ross/c++/rs_threads.tgz
I'll have to look at this later. However, if you don't have CVs then
that's at least one thing that our two implementations will have to
differ on. You *really* should get to know CVs. You'll never touch
a Win32 event object again.
> I'll probably add a few more bits to it -- there's no semaphore
class at
> the moment, and I'm dithering over whether some sort
of "synchronised
> smart pointer" template would be a good idea.
My vote is no ;). However, I'm sure Boost will have one at some
point, because some people do like them.
> (I've made one major change recently: prompted by this discussion, I
> took a more careful look at my design, and (among several smaller
> changes) decided that abandoning ("detaching" in pthreads jargon) a
> thread was never a reasonable thing to do. The Thread class's
destructor
> now blocks instead of abandoning a still-running thread.)
This was a bad decision. Think of the Win32 AVI display control.
This control spawns it's own thread to display the video frames, and
the lifetime of this thread is not bound by any programmatic block.
It really should be a detached thread (and BTW, abandoned is not the
proper Win32 terminology for this).
Bill Kempf
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk