Re: [c++-pthreads] Re: FW: RE: Re: I'm Lost
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [c++-pthreads] Re: FW: RE: Re: I'm Lost



Dave Butenhof <david.butenhof@xxxxxx> writes:

> Perhaps I'm worried about thought models and implementation while you're 
> concerned with appearance. Both views are certainly valid within certain 
> domains.

I don't know what you meant by "appearance," but I'm concerned exactly
with thought models.  From the point of view of all the things one has
to think about to decide how cancellation exceptions will act, whether
it's possible to handle them correctly, etc., the fact that they are
ultimately initiated by asynchronous events is totally irrelevant.
They could just as easily be triggered by reading from stdin at each
cancellation point to decide whether to throw.  So I'd prefer to keep
the conversation simple.  If you'd rather be precise and talk about
asynchronous cancellation while always mentioning synchronous
exceptions as a response in the same breath, that's fine with me.  in
this context, though, it's more confusing than necessary, especially
If you don't mention synchronous exceptions in the same breath (note
that you confused me).

> "Asynchronous cancelability type" is (at least potentially) an 
> asynchronous EXCEPTION in response to an asynchronous event, while 
> "deferred cancelability type" is a synchronous (deferred) exception in 
> response to the same asynchronous event. 

If you insist.  

> Does that help?

I don't think it helps in this conversation, but suit yourself; we now
understand each other.

>>> However, when cancellation is enabled, any blocking call (or any
>>> method/operator that makes or might make a blocking call, like
>>> "cout<<", might raise an exception. Not all code will be prepared to
>>> handle that, and much shouldn't be; it's important to be able to
>>> disable cancelability dynamically over critical scopes. It's not
>>> like most exceptions where the conditions for an exception are
>>> generally static; it could happen at any time for reasons the
>>> current thread cannot possibly anticipate.
>>>     
>> That's exactly like most exceptions (c.f. out-of-memory).  Usually
>> conditions whose reasons can be anticipated can be effectively tested
>> and become preconditions or simply should be reported by other means.
>>   
> Sometimes. Exceptions are great for "out of band" notifications that may 
> not be intended for the direct caller; they can be picked up with full 
> state, and without additional mechanism, by anyone along the call path 
> who cares.

I know that.  I did say "most," didn't I?  

To get things back on track, your assertion was that the reasons for
most exceptions can be anticipated.  I'm not _precisely_ sure what you
meant by "reasons ... anticipated," but I think I have a pretty good
idea, and my assertion was that most exceptions are in fact just like
that, making this particular aspect of asynchrony uninteresting as a
distinction.

>>> and I'm much less ignorant than I was 2 years ago when I started
>>> working with C++ and STL on a regular basis. Still, I am not steeped
>>> in the history and tradition of C++ as I am in threads, and probably
>>> never will be. More than that, while I have an authoritative voice
>>> on the POSIX working group and in the community, I'm not involved
>>> with the C++ committee and have no time or management support to get
>>> involved; and I won't put myself in the position of being an outside
>>> expert in some other area pretending to tell the C++ committee what
>>> it must (or even should) do.
>>>     
>> I don't think you should.  There are other areas where you could make
>> a big difference, though, like the ISO committee for C++/POSIX binding
>> Mr. Drepper is now running.
>>   
> "ISO committee" is rather a strong description; it's a simple mailing 
> list that's hoping to gain some preliminary consensus towards 
> constructing a formal proposal to request permission to develop a 
> charter and start a working group with the intent of building a proposal 
> for a binding. 

That wasn't my impression, but maybe I misinterpreted the announcement
I saw.

  The IEEE, Portable Applications Standard Committee, has just
  approved the formation of a "C++ Bindings Study Group" to
  investigate providing C++ bindings to the current POSIX Standard,
  IEEE Std 1003.1.  If the group concludes that C++ bindings should be
  done, they will generate a request to IEEE PASC for project approval
  to develop a POSIX C++ bindings specification.  The group is to
  report its findings to to PASC either by March 31, 2007, or within
  12 months of it's first meeting, whichever comes first.  The group
  will be chaired by Ulrich Drepper of Red Hat (drepper@xxxxxxxxxx).

OK, it's a study group.  Slightly more than a mailing list, but hardly
a committee.  I guess I'm just alarmist.

> But, yeah, OK, fine. ;-)

OK, thanks.

>>>> No, I wasn't suggesting anything that couldn't be caught.  I was just
>>>> suggesting an exception that couldn't be stopped.  It could throw
>>>> itself in its dtor (not that I'm advocating it, but it might satisfy
>>>> the "other side"), for example.
>>>>       
>>> The POSIX model where cancel propagates inexorably to thread
>>> termination is an inherently flawed compromise; but simply the best
>>> we could do within the context of ISO C and POSIX APIs. OUR
>>> implementation always allowed finalization, via C++ catch(...), our
>>> ISO C "CATCH_ALL" extensions, or whatever other language syntax
>>> might fit.
>>>
>>> I really wouldn't want to propagate this restriction to C++.
>>>     
>> Be clear, I'm not talking about a restriction.  If you ask it to throw
>> something normal, it's finalizable in the normal way.  This is a way
>> for the _cancelling_ thread to say, "I know what I'm doing; the author
>> of the thread I'm cancelling doesn't.  Force it to be killed at the
>> next cancellation point."
>>   
> The whole concept of cancellation is exactly that the TARGET thread, not 
> the cancelling thread, knows what it's doing and should control the 
> cleanup and termination entirely. 

Believe me, I agree.  You said we had to look for compromises, so
that's what I was doing.

> Without explicit synchronization, the cancelling thread can't know
> what it's doing and whether a forced abort is appropriate or
> safe. And if it has enough synchronization to know that, there are
> far better ways to gain a cooperative termination than cancellation.

Sure.

>>> One advantage, though, of the single cancel exception, is that it's
>>> universal. When you asynchronously issue a cancel request for a
>>> thread, you can't really know what code is executing: your's, STL,
>>> some other shared library, etc. Cancel means the same to all of
>>> them, and either is supported with commonly agreed semantics or
>>> will be ignored (by disabling cancellation in critical
>>> scopes). Once you start firing off your own arbitrary exceptions,
>>> though, anything might happen because half the time the exceptions
>>> won't belong anywhere in the call tree that's active at the time
>>> they arrive.
>>>     
>> That's not the way most exception-safe code works.  It goes to the
>> reason that exception-specifications are a failure: the particular
>> type of exception that propagates out of a throwing function makes
>> almost no difference to anyone.  The type only becomes important where
>> errors are reported, or where exceptions are translated -- either to
>> other exception types or, for example, to error return codes that can
>> propagate through other languages.  So the danger of injecting an
>> arbitrary exception type into existing code (especially libraries,
>> which are very often exception-neutral) is very very low.
>>   
> That's an intriguing statement. I'll need to think about that some.
>
> I've certainly always thought that exception specifications were little 
> more than a trap into which people could mire themselves as deeply as 
> they like. So maybe that means I agree. I'm not sure. ;-)
>
> I guess I'd have to agree that the danger of injecting another exception 
> type is low. And mostly due to the fact that C++ has no "root exception 
> type" onto which could be grafted some minimal universal state 

It has a de-facto root type: std::exception.

> (an architected status code space, like VMS condition codes, a
> descriptive string, etc.) so that nobody would need an anonymous and
> semantic-free catch(...) just to be sure nothing slipped past.

When you have a root type, catching that is practically anonymous and
semantic-free.  It doesn't make much difference in practice.

>>> Which brings us back to the "academic" resolution: if an exception
>>> means distinct things in different call trees, those call trees
>>> should be distinct threads and only one universal exception is
>>> necessary. ;-)
>>>     
>> I think you might be missing the point.  I am proposing the
>> generalized 
>>
>>   thread_throw( thread_id, exception_object )
>>
>> function so that those who wish to hang themselves with homegrown
>> unstoppable exception types can do so without forcing the standard to
>> sanction the use of unstoppable exceptions by providing any kind of
>> "forced cancellation."  If "the other side" has A WAY to force
>> cancellation, maybe they won't insist it has to be THE WAY.  I know,
>> wishful thinking :)
>>   
> I'm not sure how sanctioning generalized unstoppable exceptions 

I said I'm not sanctioning such a thing.  You can build one today in
standard C++ (it throws a copy of itself from its destructor), so
there's no need.  And of course we can't stop people from building
them.

> is going to mollify anyone opposed to an unstoppable variety of a
> specific exception.

Huh?  Did you really mean "UNstoppable?"  IIUC, you and I are both
opposed to unstoppable thread cancellation.  Are you saying you would
need to be mollified in order to accept it, even if it's only
available by hand-writing a very strange exception type?

> At best, cancel becomes a subset of cross-thread throw with 
> specialized additional deferral semantics. 

Additional?  I'm lost again.  There is no workable cross-thread throw
without deferral.  Anything else is an asynchronous exception.

> And if you're generalizing the unstoppable exception, 

Generalizing?

> I don't quite see how it makes sense not to generalize the deferral,
> and now cancel really is just a specific predefined exception that
> can be thrown like any other exception.  That's not necessarily bad;
> I just don't see how it's a compromise. (A compromise needs to make
> BOTH sides equally unhappy, not just one side!)

The compromise I'm proposing makes it possible to generate an
unstoppable cancellation (bad for us) while making it ugly and
unnatural to do so (bad for "the other side").

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com