This chapter describes the Palm OS "Try/Catch" exception-handling mechanism. It is organized into the following sections:
ErrTryCatch Structures and Types
ErrTryCatch Functions and Macros
The header file ErrTryCatch.h
declares the API that this chapter describes.
For instructions on using these APIs to throw and handle exceptions, see "The Try-and-Catch Mechanism."
ErrTryCatch Structures and Types
ErrExceptionType Struct
Purpose
An ErrExceptionType
structure is created for each ErrTry
and ErrCatch()
block. At any point in the program, there is a linked list of these structures. An ErrExceptionType
structure stores information about the state of the machine (register values, an error code, and the address at which the error occurred) at the start of the ErrTry
block.
Declared In
ErrTryCatch.h
Prototype
typedef struct ErrExceptionType { struct ErrExceptionType *nextP; ErrJumpBuf state; int32_t err; VAddr errVAddr; } ErrExceptionType
typedef ErrExceptionType *ErrExceptionPtr
Fields
-
nextP
- Next
ErrExceptionType
structure in the linked list. -
state
- Environment storage for
ErrSetJump()
/ErrLongJump()
. -
err
- Error code.
-
errVAddr
- Address reference that caused the fault.
ErrJumpBuf Typedef
Purpose
Contains state information for ErrSetJump()
/ErrLongJump()
. Used in the ErrExceptionType
structure.
Declared In
ErrTryCatch.h
Prototype
typedef long *ErrJumpBuf[16]
ErrTryCatch Functions and Macros
ErrCatch Macro
Purpose
Marks the end of an ErrTry()
block and the beginning of an ErrCatch
block.
Declared In
ErrTryCatch.h
Prototype
#define ErrCatch (
inErr
)
Parameters
-
→ inErr
- An exception code identifying the reason for the failure. This is the value supplied to the
ErrThrow()
call that caused the jump to thisErrCatch
block.
Returns
Comments
ErrCatch
can only be used in conjunction with ErrTry()
and ErrEndCatch
. See the comments under ErrTry
for usage instructions.
ErrTry
, ErrCatch
and ErrThrow
are based on setjmp
(ErrSetJump()
) and longjmp
(ErrLongJump()
). At the beginning of an ErrTry
block, setjmp
saves the machine registers. ErrThrow
calls longjmp
, which restores the registers and jumps to the beginning of the ErrCatch
block. Therefore, any changes in the ErrTry
block to variables stored in registers aren't retained when entering the ErrCatch
block.
The solution is to declare variables that you want to use in both the ErrTry
and ErrCatch
blocks as "volatile". For example:
volatile long x = 1; // Declare volatile local variable ErrTry { x = 100; // Set local variable in Try ErrThrow(-1); } ErrCatch(inErr) { if (x > 1) { // Use local variable in Catch SysBeep(1); } } ErrEndCatch
If you have many local variables after the ErrCatch
you may want to put the ErrTry
and ErrCatch
in a separate enclosing function.
ErrCatchWithAddress Macro
Purpose
Marks the end of an ErrTry()
block and the beginning of an ErrCatch
block. Unlike ErrCatch()
, this macro works with ErrThrowWithAddress()
to give the address reference that caused fault, if such an address.
Declared In
ErrTryCatch.h
Prototype
#define ErrCatchWithAddress (inErr
,inErrVAddr
)
Parameters
-
→ inErr
- An exception code identifying the reason for the failure. This is the value supplied to the
ErrThrowWithAddress()
call that caused the jump to thisErrCatch
block. -
→ inErrVAddr
- Address reference that caused fault, if such an address is available.
Returns
Comments
If the exception was thrown with ErrThrow()
or ErrThrowIf()
, inErrVAddr
is set to 0xffffffff
.
ErrCatch
can only be used in conjunction with ErrTry()
and ErrEndCatch
. See the comments under ErrTry
for usage instructions. Also see the comments under ErrCatch
for information on changes to variables stored in registers.
ErrEndCatch Macro
Purpose
Marks the end of an ErrCatch()
block.
Declared In
ErrTryCatch.h
Prototype
#define ErrEndCatch
Parameters
Returns
Comments
EndErrCatch
can only be used in conjunction with ErrTry()
and ErrCatch()
(or ErrCatchWithAddress()
). See the comments under ErrTry
for usage instructions.
ErrExceptionListAppend Function
Purpose
Appends an exception to the exception list.
Declared In
ErrTryCatch.h
Prototype
void ErrExceptionListAppend (
ErrExceptionType *errExceptionTypeP
)
Parameters
Returns
See Also
ErrExceptionListGetByThreadID()
, ErrExceptionListRemove()
ErrExceptionListGetByThreadID Function
Purpose
Gets the head of the exception list for a given thread, without changing the list.
Declared In
ErrTryCatch.h
Prototype
ErrExceptionType *ErrExceptionListGetByThreadID (
SysHandle iThreadID
)
Parameters
Returns
Returns the exception at the head of the exception list.
Comments
This function is designed to be used by a keeper thread.
See Also
ErrExceptionListAppend()
, ErrExceptionListRemove()
ErrExceptionListRemove Function
Purpose
Removes a specified exception from the exception list.
Declared In
ErrTryCatch.h
Prototype
void ErrExceptionListRemove (
ErrExceptionType *errExceptionTypeP
)
Parameters
Returns
See Also
ErrExceptionListAppend()
, ErrExceptionListGetByThreadID()
ErrLongJump Function
Purpose
Restores the environment saved in the specified buffer by a call to ErrSetJump()
.
Declared In
ErrTryCatch.h
Prototype
void ErrLongJump ( ErrJumpBufbuf
, int32_tresult
)
Parameters
-
→ buf
- Pointer to a buffer containing the environment to be restored ( program counter and stack pointer).
-
→ result
- Value that will appear to have been returned from
ErrSetJump()
once the environment has been restored.
Returns
ErrSetJump Function
Purpose
Saves a copy of the current environment (program counter and the current pointer to the top of the stack) for later restoration by ErrLongJump()
.
Declared In
ErrTryCatch.h
Prototype
int32_t ErrSetJump (
ErrJumpBuf buf
)
Parameters
Returns
Returns errNone
. Note, however, that when a call to ErrLongJump()
is made, the saved environment is restored, causing program execution to resume as if ErrSetJump
had just returned; the value "returned "at that time is the one specified by the call to ErrLongJump
.
ErrThrow Macro
Purpose
Cause a jump to the nearest catch block.
Declared In
ErrTryCatch.h
Prototype
#define ErrThrow (
err
)
Parameters
Returns
Comments
Use the macros ErrTry()
, ErrCatch()
, and ErrEndCatch()
in conjunction with this function.
See Also
ErrFatalDisplayIf()
, ErrNonFatalDisplayIf()
, ErrDisplay()
ErrThrowIf Macro
Purpose
If the error code parameter is other than errNone
, cause a jump to the nearest catch block.
Declared In
ErrTryCatch.h
Prototype
#define ErrThrowIf (
err
)
Parameters
Returns
Comments
Use the macros ErrTry()
, ErrCatch()
, and ErrEndCatch()
in conjunction with this function.
See Also
ErrFatalDisplayIf()
, ErrNonFatalDisplayIf()
, ErrDisplay()
ErrThrowWithAddress Function
Purpose
Throw an error to the first handler on the exception list for this thread, causing a jump to the nearest catch block. Unlike ErrThrow()
and ErrThrowIf()
, you can use this function to pass the address reference that caused the fault.
Declared In
ErrTryCatch.h
Prototype
void ErrThrowWithAddress ( int32_terr
, VAddrerrVAddr
)
Parameters
-
→ err
- Error code.
-
→ errVAddr
- Address to be reported to
ErrCatchWithAddress()
.
Returns
Comments
Use the macros ErrTry()
, ErrCatchWithAddress()
, and ErrEndCatch()
in conjunction with this function.
See Also
ErrFatalDisplayIf()
, ErrNonFatalDisplayIf()
, ErrDisplay()
ErrThrowWithHandler Function
Purpose
This function is what the keeper thread should make the faulted thread run when it resumes. This function will do the ErrLongJump()
to make the faulted thread clear its stack and jump to its ErrCatch()
handler.
Declared In
ErrTryCatch.h
Prototype
void ErrThrowWithHandler ( int32_terr
, VAddrerrVAddr
, ErrExceptionType*tryP
)
Parameters
-
→ err
- Error code.
-
→ errVAddr
- Address to be reported to
ErrCatchWithAddress()
. -
→ tryP
- Pointer to the exception state to be handled by
ErrCatch()
orErrCatchWithAddress()
.
Returns
Comments
This function is designed to be used by a keeper thread.
See Also
ErrFatalDisplayIf()
, ErrNonFatalDisplayIf()
, ErrDisplay()
ErrTry Macro
Purpose
Marks the beginning of a try/catch block.
Declared In
ErrTryCatch.h
Prototype
#define ErrTry
Parameters
Returns
Comments
An exception raised by a call to ErrThrow()
—even from within a nested subroutine—causes program execution to switch to the beginning of the ErrCatch()
block. If the end of the block enclosed by ErrTry
is encountered without a call to ErrThrow
, execution jumps to the line of code following the ErrEndCatch()
macro. See "The Try-and-Catch Mechanism" for a more thorough description of how this mechanism works.
Example
You must structure your code exactly as shown here. You can't use ErrTry
without ErrCatch
and ErrEndCatch
, or vice versa.
ErrTry { // Do something which may fail. Call ErrThrow to signal // failure and force a jump to the following ErrCatch // block. } ErrCatch(inErr) { // Recover or cleanup after a failure in the above ErrTry // block. "inErr" is an exception code identifying the // reason for the failure. // Call ErrThrow if you want to jump out to the next // ErrCatch block. // The code in this block doen't execute if the above // ErrTry block completes without a call to ErrThrow. } ErrEndCatch