Legacy Documentclose button

Important: The information in this document is obsolete and should not be used for new development.

Previous Book Contents Book Index Next

Inside Macintosh: QuickDraw GX Environment and Utilities /
Chapter 5 - Collection Manager / Using the Collection Manager


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 functions setjmp and longjmp 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, the ExceptionTest sample function takes a single parameter: a reference to a collection object. The sample function first calls the SetCollectionExceptionProc function to install an exception handler for this collection object. In this example, the call to SetCollectionExceptionProc installs the MyExceptionHandler function as the exception handler.

The next line of the ExceptionTest sample function calls the setjmp function. This function stores the current machine state, including the current position in the sample code, into the cpuState global variable. It also returns a value of 0 as its function result, and this value is assigned to the local variable result. This value is negated (by the ! operator), an operation that produces a Boolean value of true. Therefore, the block of code in the if clause begins to execute.

Imagine that the first call to the AddCollectionItem function completes successfully, but that the second call to AddCollectionItem generates a collectionItemLockedErr error. During the second call to AddCollectionItem, the Collection Manager responds to the error by calling the MyExceptionHandler 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 the collectionItemLockedErr error (which it is in this example) and then returns with the noErr 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, the ExceptionTest sample function continues by executing the third call to the AddCollectionItem function.

The subsequent line of the ExceptionTest sample function attempts to remove an item that is not in the collection, resulting in a collectionItemNotFoundErr error. Again, the Collection Manager responds by calling the exception handler. In this case, however, the error is not the collectionItemLockedErr error, so the exception handler executes this line of code:

longjmp(cpuState, status);

When you call the longjmp function,

Therefore, this call to the longjmp function passes control back to the location in the ExceptionTest sample function where setjmp(cpuState) was called earlier. This time, however, the function result returned by the setjmp function is not 0, as it was before, but instead is the value of status, the second parameter in the call to the longjmp function. Therefore, the function result of the setjmp function is set to be the collectionItemNotFoundErr error.

Once again, the ExceptionTest sample function assigns this function result to the result local variable, and negates it with the ! operator. This time the negation produces a Boolean value of false, and therefore the block of code in the else clause begins to execute. In this block of code, you can handle errors not handled in the exception handler, using the result 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.


Previous Book Contents Book Index Next

© Apple Computer, Inc.
7 JUL 1996