/* 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 <config/PCR←StdTypes.h> #include <setjmp.h> 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 <handler,data>. */ #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$ */