Boost logo

Boost :

From: William Kempf (williamkempf_at_[hidden])
Date: 2001-08-28 09:28:35


From: "Peter Dimov" <pdimov_at_[hidden]>
>From: "William Kempf" <williamkempf_at_[hidden]>
>>No. Adoption is a QoI issue. However, on most (obviously not all)
>>platforms even if there's multiple libraries for MT they are all based on
>>OS
>>level constructs so users expect the various wrappers to work together as
>>much as possible. Users will expect to be able to write library code that
>>works no matter what MT library someone chooses to use in the application
>>that links to it. This is not an unreasonable expectation. So a goal of
>>Boost.Threads should be (and is) to make it as easy as possible for
>>"adoption" to be implementable. The proposed interface does this.
Adoption
>>works flawlessly for both POSIX and Win32 implementations. The thread_ref
>>design, however, can't insure this, and in fact adoption on POSIX has been
>>shown to be extremely problematic with this design.
>
>Not 100% correct (AFAICS). This is not an inherent property of a
>thread_ref-based design. The "implementation defined" current() means that
>several different variations are possible:
>
>1. Fully compliant, current() works as intended no matter what (requires
>native support.) This is expected to be the behavior of a quality C++
>standard library implementation that cooperates with the native >threading
>library if there is one.
>
>2. (POSIX-based) current() works as intended provided that pthread_join()
>and pthread_detach() are never called on an adopted thread.

This is more than a tad confusing. A "POSIX-based" current() *IS* a "fully
compliant" current, no matter what definition of "compliant" you want to
choose. The minor restriction added here that "pthread_join() and
pthread_detach() are never called on an adopted thread" is, in practice,
what most code does already. This is the proposed semantic since it
provides "fully compliant" adoption on both target platforms and is likely
to allow "fully compliant" adoption on any other platform as well. It's the
only one of the options you list that can do this.

>3. (POSIX-based) current() works as intended except that an adopted thread
>is not joinable; whoever created the thread is responsible for joining or
>detaching it.

This is identical to (2).

>4. (Win32-based) current() works as intented, except that the thread object
>associated with the adopted thread is not guaranteed to persist after the
>thread_ref is destroyed. (Unless there's some clever way to implement
>cleanup handlers on win32 that I'm missing. A __declspec(thread)+destructor
>combo doesn't seem to work. A helper DLL might.)

This one is the most confusing of all (and the easier one for me to address
since I'm a Win32 programmer). First, your exception happens to be
identical to "normal Win32 behavior". A call to GetCurrentThread() returns
a "pseudo-handle" that's only valid within the current thread, and thus by
very definition does not persist after the _thread_ is destroyed (your use
of thread_ref here leads to confusion and may be the basis of the rest of
your comments here). Cleanup handlers can be implemented on Win32... but
they do require a "helper" DLL. By contrast, __declspec(thread) should be
avoided at all costs because it does not behave properly with dynamically
loaded DLLs. All that said, TLS is irrelevant here. A thread_ref design
built on top of Win32 (instead of on top of Boost.Threads) would simply be a
thin wrapper around a HANDLE, where current() calls DuplicateHandle() on the
return from GetCurrentThread(). TLS is never used. If you're talk here is
based on an implementation on top of Boost.Threads we must first define the
semantics used by it, which is a circular argument in this thread. Not to
mention such an implementation wouldn't be a "Win32-based" implementation.

>And of course
>
>5. current() cannot be used to adopts threads.

Which is simply something that users won't accept. We can't make any strong
gaurantees, but we must allow implementations to "do the best they can" in
this regard. The design I propose for use not only does this, but, again (I
can't emphasize this enough) with the current targets of Win32 and POSIX it
allows full adoption semantics.

>I should also add that when, in the future, thread cancelation is added to
>the library, canceling an adopted thread would likely lead to undefined
>behavior -- this applies to both designs. (Unless - again - I'm overlooking
>a clever solution to the problem.)

That's a different issue, and there are possible "solutions". However,
cancellation, to be safe, must be a cooperative task. Not only must another
thread ask the target thread to terminate, but the target thread must agree
to do so. This is why POSIX cancellation includes the concept of
"cancelability state". This fact helps to lessen any possible errors in
attempts to cancel "adopted" threads.

>>The complaint is that
>>the proposed design makes a thread_ref design difficult to be implemented
>>on
>>top of it, but my contention is that the issues are nearly identical to
>>implementing a thread_ref design on top of POSIX to begin with.
>
>Depends on which variation you have in mind. #2 is possible with pthreads
>but not the current Boost.Threads, #3 is possible with both -- except for
>the main thread problem with Boost.Threads.

I beg to differ. #2 is the very definition of the proposed Boost.Threads
implementation (and again I see no difference between #2 and #3). So long
as the thread_ref design uses "wait" semantics instead of "join" semantics
the implementation is identical whether done on top of Boost.Threads or
POSIX threads (provided I lift the restriction on the "current" thread
object being valid only within the current thread of execution, which I said
I could do if this were a show stopper). The *ONLY* difference between the
proposed boost::thread and POSIX pthread_t is that we have the artificial
restriction that "current" thread objects can't be "joined", but in practice
this is usually the behavior used in POSIX threads any way.

>>The one
>>difference is a theoretical allowance for the "initial thread", but I find
>>it very difficult to distinguish this thread from any other in this
regard.
>
>Just to clarify, are you saying that Boost.Threads will never allow users
>to
>join the main thread?

I don't know, frankly. In general I consider it to be a design flaw to join
the initial thread, so see no purpose in treating it any differently than
any other adopted thread. Considering how difficult it will be to
differentiate this thread from other adopted threads (do you have a proposal
on how to do so?) and that I see "joining" this thread as a design mistake,
no, I currently have no plans to allow the initial thread to be "joined".

Bill Kempf

_________________________________________________________________
Get your FREE download of MSN Explorer at http://explorer.msn.com/intl.asp


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