Boost logo

Boost :

From: William E. Kempf (wekempf_at_[hidden])
Date: 2003-06-02 11:34:24


Alexander Terekhov said:

Sorry for the late reply. I've been on vacation and away from 'net access
for a week. Still catching up on a LOT of e-mail, so I'm sure there's
been a lot of responses to this from others already, and I have not read
them yet. So bear with me.

> Alexander Terekhov wrote:
>>
>> "William E. Kempf" wrote:
>> [...]
>> > >> How about moving this discussion to c.p.t.?
>> > >
>> > > Well, just in case... <Forward Quoted>
>> >
>> > Thanks... I currently can't access c.p.t. in any reasonable manner.
>> I'm working to rectify this,
>>
>> http://news.cis.dfn.de might help. ;-)
>>
>> but in the mean time, I appreciate the
>> cross
>> > post.
>>
>> I'll wait a day or two and post a reply addressing some of your points
>> to comp.programming.threads.
>
> "just in case..." <Forward Inline>
>
> Alexander Terekhov wrote:
>>
>> <Forward-Quoted source=Boost>
>>
>> "William E. Kempf" wrote:
> [...]
>> > >> The big hurdle for a true C++ binding is that the current state
>> of affairs is "good enough" for most people, and the political
>> process of developing a full native C++ binding would be painful.
>> (Remember, it's not just saying that the thread::create method
>> takes a class member at which the thread will start... it means
>> reviewing every method and template in the STL to determine which
>> have thread safety
>> > >> requirements, and deciding precisely what those requirements are
>> and how to meet them. Then there's the matter of cancellation
>> points... and so forth.)
>> >
>> > Most STL libraries are thread-safe today, so the analysis there
>> wouldn't be too difficult.
>
> Well, <http://lists.boost.org/MailArchives/boost/msg47701.php>.

Yes. I didn't mean to indicate there was *no* evaluation to be done.
Only that the lion's share has already been done by library implementers
today.

>> > It just needs to be stated explicitly in the
>> standard.
>> > Cancellation points are another issue... but I don't think C++ will
>> add too many to the list already provided by POSIX.
>
> The current C++ Std is in conflict with POSIX, to begin with.

Not exactly. POSIX specifies C language extension libraries. As such,
there is no relationship to C++ at all. They're not part of the C
standard, so C++ doesn't address them, while POSIX doesn't address
bindings for any language but C. So the "conflict" is that they are
simply unrelated. If POSIX were to submit their libraries for inclusion
in the C standard, then things would be a little different. However, the
C++ standard does not gaurantee that it will track the C standard's future
changes. In fact, there are incompatibilities with C99 already. There is
incentive to do so (for instance, they are discussing how to integrate the
C99 changes), but since they are seperate standards this may not always be
possible.

> The C++
> standard says that almost the entire C library doesn't throw (in effect,
> everything is throw()) except just a few calls for which C++ headers
> provide extern "C++" overloading to facilitate C++ callbacks. In POSIX,
> a whole bunch of standard C library functions DO "throw" due to thread
> cancelation. Isn't that funny?

Not really funny. But POSIX doesn't specify that cancellation results in
a C++ exception being thrown either. So there's no technical conflict
here, even if there's all sorts of headaches for users. I hope this
improves from our efforts, but there's no gaurantee, since, again, they
are seperate and unrelated standards. In the mean time, this results in a
QOI issue.

>> > >> When and if the C++ standard adds true thread support, that will
>> be, by default and in practice, the thread binding for C++;
>> whether the underlying thread environment is POSIX, Win32, or
>> something else. This is great, as long as it doesn't do or say
>> anything stupid, but it still leaves a few loopholes because
>> inevitably people will continue to write applications that mix
>> languages. Mixing C and C++ has never been a problem; but if the
>> thread model in C++ is radically different, it could become a
>> problem.
>> >
>> > Absolutely agreed. I've said all along that Boost.Threads has to be
>> very aware of what POSIX says. We can not deviate in any way from
>> POSIX that will result in conflicts between the threading systems.
>
> Bill, Boost.Threads shall end up in standard <thread> header. But there
> should also be a <cthread> standard header (it should penetrate ISO C as
> well; in the form of either <pthread.h> or <cthread.h> header). Now, in
> the past, I was thinking of <thread> as "just" an object layer on top
> of <cthread> stuff. That was wrong. <cthread> should be fully
> implementable using stuff from <thread>. I mean things along the lines
> of:

I see no reason for C++ to include a <cthread>, unless it's there for
compatibility with a C <thread.h>. IOW, POSIX should address the C
standard first, not the other way around. (And not all of POSIX is
necessarily appropriate, either, as the impact to non-POSIX platforms can
be quite extensive and you are likely to find opposition from those
members.)

> typedef std::thread * pthread_t;
>
> extern "C" pthread_t pthread_self() throw() {
> return std::thread_self().raw_ptr();
> }
>
> typedef thread_specific_ptr<void, __c_TSD_cleanup> * pthread_key_t;
>
> extern "C" int pthread_key_create(pthread_key_t * key,
> void ( * dtor)(void *)) throw() {
> try {
> // can throw "shall fail" stuff only (std::bad_alloc and
> std::try_again) *key = new pthread_key_t(__c_TSD_cleanup(dtor));
> // "may fail" shall be caught in the std::unexpected() handler
> }
> catch(...) {
> return
> __translate_exception_to_error_code_using_throw_and_catch();
> }
> return 0;
> }
>
> typedef std::aligned_storage<std::mutex> pthread_mutex_t;
> typedef std::aligned_storage<std::mutexattr_t> pthread_mutexattr_t;
>
> extern "C" int pthread_mutex_init(pthread_mutex_t * mutex_storage,
> const pthread_mutexattr_t * attr_storage)
> throw() {
> try {
> // can throw "shall fail" stuff only
> new (mutex_storage->place()) std::mutex(attr_storage->object());
> // "may fail" shall be caught in the std::unexpected() handler
> }
> catch(...) {
> return
> __translate_exception_to_error_code_using_throw_and_catch();
> }
> return 0;
> }
>
> extern "C" int pthread_mutex_destroy(pthread_mutex_t * mutex_storage)
> throw() {
> // destructor with implicit throw()-nothing ES
> ~mutex_storage->object();
> // "may fail" shall be caught in the std::unexpected() handler
> return 0;
> }
>
> #define PTHREAD_CANCELED std::thread_canceled()
>
> extern "C" void pthread_exit(void * ptr)
> throw(std::thread_termination_request) {
> (ptr == PTHREAD_CANCELED) ? std::thread_cancel() :
> std::thread_exit(ptr);
> }
>
> using stuff from <thread>:
>
> struct thread_canceled {
> operator void * () { return &unique; }
> static thread_canceled unique;
> };
>
> template<typename T>
> void thread_exit(T value) {
> assert(std::thread_self().can_exit_with<T>());
> throw thread_exit_value(value);
> }
>
> template<>
> void thread_exit(std::thread_canceled) {
> thread_cancel();
> }
>
> void thread_cancel() {
> throw std::thread_cancel_request();
> }
>
> or something like that.

Give me a valid reason for having a C style interface and I'll certainly
consider adding it to Boost.Threads and recommending it to the committee.
But I don't see a need for it myself.

>> > >> Furthermore, there's a missing piece that
>> > >> neither POSIX 1003.1-2001 plus ISO C++ 2005 (or whatever), or
>> even 1003.1-2001 plus a hypothetical "1003.C++" will necessarily
>> (or even likely) supply -- and that's how the two interoperate.
>> >
>> > Agreed, but that's the case today when mixing languages. There are
>> a lot of areas which are left unspecified, even when the languages
>> being mixed are C and C++.
>
> C and C++ WILL merge, sooner or later. The separation of C and C++
> languages is/was the stupidest thing C++ authors ever did (or allowed
> to happen). Well, just look what's going on with respect to GCC/G++
> (adding exceptions and C-destructors IS kinda "merging", I believe).

Strong words (you did the shouting), with no indication this is so from
any of the people who would dictate this. Or did I miss something? I'm
not at all sure it make sense for C and C++ to merge. But if it ever
does, they will address those problems then. I don't see much that I can
do today to help in this regard.

>> > >> If C++ or 1003.C++ says that thread::cancel raises an exception,
>> and 1003.1 says that pthread_cancel() invokes cleanup handlers,
>> does that mean that cancelling a thread with pthread_cancel()
>> will trigger catch(...), or even destructors? Well, maybe not.
>> This could more easily be solved with a 1003.C++, perhaps, since
>> at least the two standards are in a family. Since the C++
>> standard is unlikely to mention POSIX any more than now, it's
>> unlikely to provide any guarantees.
>> >
>> > No gaurantees. But with a C++ definition, one can at least hope
>> that implementations will try and deal with these cross-language
>> binding issues in some reasonable manner.
>
> *You* should do it for "C subset of C++" (incompatibilities and
> "restrict"-like extensions of ISO-C aside for a moment). There will be
> NO problems with cross-C/C++-language bindings if Boost would come up
> with some "reference implementation" (see above) of <cthread>
> (i.e. also <pthread.h>) using stuff from the REAL <thread> header.

There is no "C subset of C++" that addresses threading. Again, if you
want that, address the C standard first.

> You did not seem to like to "force" windows user of Boost.Threads to
> download pthreads-win32 and use Boost.Threads on top of it. YOU'RE
> RIGHT! Pthreads-win32 will be shutdown as soon as you'll deliver a
> <cthread> and <pthread.h> beasts implemented using stuff from the
> "boosted" <thread>. And, perhaps, then even Microsoft will follow...
> delivering a much better implementation of BOTH (including fully
> supported cancelation for all C and C++ standard calls meant to throw
> std:thread_cancel_request exception).

Interesting thought, but you've not supplied a reason for me to be
interested in a C binding. And if I were, I'm not sure how the
implementation would be factored... the layering approach will add
overhead that may or may not be important.

>> > >> Perhaps that would provide an opportunity for a smaller POSIX
>> project, though; a PROFILE that would chink the holes where the
>> two walls meet. In effect, specifying a "POSIX platform"
>> supporting both threads and C++ that simply says "C++
>> cancellation is the same as POSIX cancellation", "POSIX cleanup
>> handlers are logically and semantically the same as C++ object
>> destructors", and "POSIX cancellation is visible as a C++
>> exception".
>> >
>> > Reasonable things for POSIX to do, or at least consider, IMO.
>
> Hardcore POSIX folks don't really "think C++", unfortunately. The only
> way to get it done is to deliver POSIX threading API implementation "on
> top" of Boost.Threads to them, I think. Well, this would also mean a
> whole bunch of extensions to the current POSIX threading -- things like
> parameterized pthread_once() and TSD destructors (to support shared_ptr
> like "custom deleters" without too much overhead), etcetera.
>
> What do you think?

I understand your motivations. There's a lot to be said to get all of the
players (C/C++/POSIX) intimately involved with each other. But I think
you're suggesting going about it wrong. First, POSIX should be added to
the C standard (or portions of it, if that's what the committee members
deem appropriate). Then we can try and address the C/C++ boundary
issues... if possible. I'm not sure you'll ever be able to address all of
them, since they ARE sperate languages, beyond a QOI issue.

-- 
William E. Kempf

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