This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Interleaving pthread_cleanups in C and C++
Richard Henderson <rth@redhat.com> writes:
> On Sat, May 03, 2003 at 06:08:09PM -0700, Mark Mitchell wrote:
>> (1) pthread cancellation should be just an ordinary exception -- not
>> "forced unwinding". That should be reserved for longjmp_unwind.
> [...]
>> I think (1) is the clear consensus position among the C++ people who
>> have commented.
>
> Now that we've allowed catch-all handlers to trigger, I don't
> believe you can tell the difference, so I don't see what it
> really matters.
Making it a real C++ exception allows one to do things like use it
in throw specs; catch it specifically; catch everything but it; etc.
Basically it allows a bunch more flexibility on the C++ side of the
fence.
> First, I very much dislike intertwining libc internals into libgcc
> in this fashion. I don't think I can stress this enough.
>
> Second, while you don't need unwind info for C only, you DO need it
> for mixed C and C++, which is the only time you're going to care
> about whether exceptions run C cleanups. The reason is that if you
> can't unwind the stack, you can't find the next C++ frame, which means
> that you won't find the next C++ frame's catch handler.
>
> Third, the C sjlj has quite a bit of overhead preparing for the
> exception even when it does not occur. The libc people complain
> about this every so often. A pure libunwind solution with try/finally
> would have no such setup overhead.
Mark's proposal IMHO goes way too far down the "anything but a
language extension!" road; however, I am a little leery of generic
try/finally in C, given the objections raised way back when, and
besides which it isn't clear to me that try/finally are really what is
wanted. It seems to me that the appropriate extension is a subset of
C++'s destructor functionality, allowing one to write something like
this:
typedef void (*__pthread_cleanup_handler) (void *);
struct __pthread_cleanup {
__pthread_cleanup_handler handler;
void *arg;
bool execute;
~__pthread_cleanup() { if (execute) handler(arg); }
};
#define pthread_cleanup_push(H, A) \
{ struct __pthread_cleanup __pc = { (H), (A), true };
#define pthread_cleanup_pop(E) \
__pc.execute = E; }
zw