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++
Zack Weinberg <zack@codesourcery.com> writes:
> 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; }
Perhaps even
#define pthread_cleanup_push(H, A) \
{ struct __pthread_cleanup __pc = { (H), (A), true } \
__attribute__((cleanup (__pthread_cleanup_routine)));
void __pthread_cleanup_routine (struct __pthread_cleanup *s)
{
if (s->execute)
(s->handler) (s->arg);
}
that way you don't need any tricky syntax extensions.
--
- Geoffrey Keating <geoffk@geoffk.org>