/* Copyright (c) 1993 Xerox Corporation. All rights reserved. */ /* $Id$ $Date$ * * Public definitions for PCR UnwindProtection * */ #ifndef __PCR_ThUWProt_h #define __PCR_ThUWProt_h 1 #include #include extern const PCR_Any PCR_ThUWProt_id_LONGJMP; extern const PCR_Any PCR_ThUWProt_id_EXIT; extern const PCR_Any PCR_ThUWProt_id_LEAVE; typedef struct PCR_ThUWProt_ExitArgsRep { int ea_code; PCR_Any ea_val; } PCR_ThUWProt_ExitArgs; typedef void PCR_ThUWProt_Handler(PCR_Any id, PCR_Any arg, void *data); /* Called (with signals disabled and id == PCR_ThUWProt_id_LONGJMP) by any call to longjmp()/siglongjmp() that would unwind past the frame from which the handler was installed (i.e. that would remove the frame). Called (with all signals blocked and id == PCR_ThUWProt_id_EXIT) by any call to exit(). In this case arg is a (PCR_ThUWProt_ExitArgs *) value containing the args to exit. Called (with all signals blocked and id == PCR_ThUWProt_id_LEAVE) by any call to PCR_ThUWProt_Leave(), below. Called (with all signals blocked and id the address of some unique object) by PCR_ThUWProt_Unwind(), below. If an unwind handler itself calls longjmp/siglongjmp or exit, or if it enables signals and the signal handler does so, the handler will *not* be reentered recursively. NOTE: Frames are in general associated with C procedures, *not* C blocks. The use of (sig)setjmp and UnwindProtect in the same C procedure is almost guaranteed not to work right, and is discouraged. Nested uses of PCR_ThUWProt_ENTER - PCR_ThUWProt_LEAVE pairs are okay. */ typedef volatile struct PCR_ThUWProt_HandlerRecordRep PCR_ThUWProt_HandlerRecord; typedef PCR_ThUWProt_HandlerRecord * PCR_ThUWProt_HandlerRecordPtr; struct PCR_ThUWProt_HandlerRecordRep { /* private */ PCR_ThUWProt_HandlerRecordPtr uwphr__next; /* public */ PCR_ThUWProt_Handler * uwphr_proc; void * uwphr_data; }; /* Unwind-protect handler record. This *must* be an automatic variable in the frame being protected. The safest thing to do is to use the macros PCR_ThUWProt_ENTER / PCR_ThUWProt_CANCEL / PCR_ThUWProt_LEAVE defined below. */ extern void PCR_ThUWProt__Enter(PCR_ThUWProt_HandlerRecordPtr uwphr); /* Enter an extent unwind-protected by . */ #define PCR_ThUWProt_Enter(uwphrp,p,d) { \ (uwphrp)->uwphr_proc = (p); (uwphrp)->uwphr_data = ((void *)(d)); \ PCR_ThUWProt__Enter(uwphrp); } #define PCR_ThUWProt_ENTER(p,d) { PCR_ThUWProt_HandlerRecord __uwphr; \ PCR_ThUWProt_Enter(&__uwphr,(p),(d)) extern void PCR_ThUWProt_Cancel(); /* Leave an unwind-protected extent without calling the handler proc. */ #define PCR_ThUWProt_CANCEL() { PCR_ThUWProt_Cancel(); }} extern void PCR_ThUWProt_Leave(); /* Leave an unwind-protected extent, calling the handler with id == PCR_ThUWProt_id_LEAVE. */ #define PCR_ThUWProt_LEAVE() { PCR_ThUWProt_Leave(); }} extern void PCR_ThUWProt_Unwind(PCR_Any id, PCR_Any arg); /* Walk the stack, calling all unwind handlers with the specified id, (which should not be one of the PCR_ThUWProt_id_XXX consts above) and the specified arg. If all the handlers return, this terminates the thread. */ #endif /* ! __PCR_ThUWProt_h */ /* $Log$ */