Re: [c++-pthreads] Re: thread-safety definition
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [c++-pthreads] Re: thread-safety definition



On Mon, Jan 12, 2004 at 07:19:42PM +0100, Alexander Terekhov wrote:
> Ted Baker wrote:
> [...]
> > There is no need for a destructor to be aware of cancellation.
> 
> my_file::~my_file() throw() {
>   fclose(/*...*/); // doesn't throw; cancel is unexpected (even if thread
>                    // cancel state is equal here to PTHREAD_CANCEL_ENABLE)
> }

Yes, in my model, cancel state would *always* be equal to
PTHREAD_CANCEL_DISABLE in the my_file (and my_other_file)
destructors, and so fclose() cannot throw cancellation.

> void jason() throw() {
>   std::enable_thread_cancel(); // re-enable cancel state
>   std::thread_self().cancel(); // re-inject cancel request
> }

> my_other_file::~my_other_file() throw() {
>   bool canceled_before = std::unwinding<std::thread_cancel_request>(this);
>   try {
>     if (canceled_before) jason();
>     fclose(/*...*/); // can (should "if (canceled before)") throw
>     /*std::*/pthread_testcancel(); // fix "may occur" mess
>   }
>   catch (std::thread_cancel_request const &) {
>     if (!canceled_before) jason();
>   }
> }

What is the purpose of the above?  That is, why are you
intentionally shooting yourself in the foot, by enabling
cancellation and then explicitly catching it in ~my_other_file()?
I guess you have a reason, but I don't see it.  This seems to just
makes ugliness without any apparent benefit.  You can just call
fclose() by itself (without the thry...catch), since cancellation
is disabled, as in ~my_file().

(BTW, I would prefer to see code that does this sort of explicit
playing with cancellation state and catching of cancellation
required to provide some sort of syntactic override, so that
people are less likely to inadvertently shoot their feet.)

> Now, in your model with cancellation ALWAYS disabled while running 
> destructors (not only when acting upon a cancel request delivery... 
> thread_exit aside for a moment), I'd have to add enable/disable RAII

Please translate "RAII" for me?

> guard object (and that's in addition to save-disable/restore internal

Why do you say that would require you to add a guard object?

> "C++ runtime" managment cost)... and I'd probably have to get rid of 
> ability to control cancelability of ~my_other_file() internal stuff 
> via thread cancel state set outside. Oder? I really don't like that.

> [...]
> > > Burning processing cycles on cancel enable/disable is another issue
> > > here, BTW.
> > 
> > Yes, but it need not be a *huge* amount of cycles.  ...
> 
> ES (throw specs) should have no runtime cost other than some extra 
> info for the search phase. OTOH, save-disable/restore burns cycles 
> (keystrokes aside for a moment) no matter whether you hit some 
> cancellation point [or async-cancel region] *with cancel request 
> pending* or not. 

The overhead for enabling/disabling cancellation is not paid on what
you are calling "throw specs" until an exception is thrown
and the code is actually executed to process the exception.

It would be paid, however, on all (groups of) destructors,
regardless of when they are executed.

This overhead could be reduced if one is willing to make
cancellation-disabled the default thread state, and use syntactic
markers to identify cancellation-enabled subprograms.  In that
case, you would only need to do the save-disable/restore code for
destructors (and other non-cancellation-enabled subprograms) that
are called from cancellation-enabled subprograms.

--Ted