/*
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$
*/