Important: The information in this document is obsolete and should not be used for new development.
Installing an Exception Procedure
The Collection Manager allows you to specify an exception procedure for each collection object. When you attempt to manipulate a collection object using a Collection Manager function and the function results in an error, the Collection Manager calls the exception procedure for the collection object and sends it two parameters: a reference to the collection object that caused the error and the error code that was generated.In an exception procedure, you can handle the error and then change the error code to
noErr
, a process which indicates that the Collection Manager can return control to the place in your application that generated the error as if no error had occurred. You can also change the error from one error code to another. A third alternative is to use the ANSI C functionssetjmp
andlongjmp
to jump out of the exception handler and into code to handle the error. Listing 5-27 shows a sample exception procedure.Listing 5-27 A sample exception procedure
jmp_buf cpuState; /* global machine state */ pascal OSErr MyExceptionHandler(Collection errorCollection, OSErr status) { /* ignore collectionItemLockedErr errors */ if (status == collectionItemLockedErr) return noErr; /* all other errors must be handled by caller's setjmp block */ /* jump back to callers setjmp block and return status */ longjmp(cpuState, status); } void ExceptionTest(Collection anyCollection) { OSErr result; SetCollectionExceptionProc(anyCollection, MyExceptionHandler); if (!(result = setjmp(cpuState))) { AddCollectionItem(anyCollection, 'tag1', 1, 4, "data"); AddCollectionItem(anyCollection, 'tag1', 2, 9, "more data"); AddCollectionItem(anyCollection, 'tag1', 3, 9, "last data"); /* cause an error . . . */ RemoveCollectionItem(anyCollection, 'tag1', 4); } else { . . . /* handle errors other than collectionItemLockedErr */ /* use result local variable to determine which error */ . . . } }In Listing 5-27, theExceptionTest
sample function takes a single parameter: a reference to a collection object. The sample function first calls theSetCollectionExceptionProc
function to install an exception handler for this collection object. In this example, the call toSetCollectionExceptionProc
installs theMyExceptionHandler
function as the exception handler.The next line of the
ExceptionTest
sample function calls thesetjmp
function. This function stores the current machine state, including the current position in the sample code, into thecpuState
global variable. It also returns a value of 0 as its function result, and this value is assigned to the local variableresult
. This value is negated (by the!
operator), an operation that produces a Boolean value oftrue
. Therefore, the block of code in theif
clause begins to execute.Imagine that the first call to the
AddCollectionItem
function completes successfully, but that the second call toAddCollectionItem
generates acollectionItemLockedErr
error. During the second call toAddCollectionItem
, the Collection Manager responds to the error by calling theMyExceptionHandler
function. The first parameter passed to this function indicates the collection that generated the error, and the second parameter passed to this function indicates the error that was generated. This sample exception handler determines whether the error is thecollectionItemLockedErr
error (which it is in this example) and then returns with thenoErr
error as the function result. The Collection Manager notices this change in error and returns control to the sample function as if no error had occurred. (Just as you can use this mechanism to ignore certain errors, you can also use this mechanism to change errors of one type into errors of another type.) Since effectively no error has now occurred, theExceptionTest
sample function continues by executing the third call to theAddCollectionItem
function.The subsequent line of the
ExceptionTest
sample function attempts to remove an item that is not in the collection, resulting in acollectionItemNotFoundErr
error. Again, the Collection Manager responds by calling the exception handler. In this case, however, the error is not thecollectionItemLockedErr
error, so the exception handler executes this line of code:longjmp(cpuState, status);
When you call the
longjmp
function,
Therefore, this call to the
- control is passed to the location of the corresponding call to the
setjmp
function- the value passed as the second parameter to the
longjmp
function becomes the function result of thesetjmp
function
longjmp
function passes control back to the location in theExceptionTest
sample function wheresetjmp(cpuState)
was called earlier. This time, however, the function result returned by thesetjmp
function is not 0, as it was before, but instead is the value ofstatus
, the second parameter in the call to thelongjmp
function. Therefore, the function result of thesetjmp
function is set to be thecollectionItemNotFoundErr
error.Once again, the
ExceptionTest
sample function assigns this function result to theresult
local variable, and negates it with the!
operator. This time the negation produces a Boolean value offalse
, and therefore the block of code in theelse
clause begins to execute. In this block of code, you can handle errors not handled in the exception handler, using theresult
local variable to determine which error occurred.You can find more information about the
SetCollectionExceptionProc
function on page 5-59. You can find more information about exception procedures on page 5-101.