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: Programmer's Guide to MacApp / Part 2 - Working With MacApp
Chapter 24 - Working With Memory and Failure Handling


Recipes--Memory (68K Only)

The recipes and sample code in this section present a system for defining segment names and also demonstrate how to fine tune memory usage by defining 'res!' and 'seg!' resources for your application. These recipes all involve segments--thus they are used only by 68K applications.

For detailed information on MacApp segmentation issues, see "Segmenting a 68K Macintosh Application," beginning on page 75.

Recipe--Defining Segment Names for Your Application

This recipe describes a strategy for naming segments in your application by combining two aspects of each routine you place in a segment: a short code for the unit the routine resides in and a second code based on when the code is called (the phase of application execution when the code is called). This strategy is based on the strategy used by MacApp itself.

The unit part of the segment name can be something like the following (a partial list):

App
For the application unit
Doc
For the document unit
Pref
For the preferences unit
View
For the view unit
The execution part of the segment name can be something like the following
(a partial list):
Cursor
HandleCursor and DoSetCursor and related routines (called frequently from the main event loop)
DoCommand
DoIt, UndoIt, and RedoIt routines
Help
Balloon Help routines
Init
Routines used only at application initialization (not resident!)
Patch
Called from patches or VBL tasks (make resident)
Print
Printing routines
ReadFile
Routines used in opening an existing document
Res
Resident code (don't overuse)
SelCommand
Handle routines (HandleEvent, HandleKeyUp, and so on) and Do routines (DoEvent, DoKeyUp, and so on)
WriteFile
Routines used in saving a document
For each routine in your application, you create a segment name by combining the code for its unit and the code for when it is executed. For example, routines from the document unit for reading a document go in the DocReadFile segment. Routines for writing a document go in the DocWriteFile segment. Routines from the view unit that handle the cursor go in the ViewCursor segment.

You specify a segment for a routine by placing a #pragma segment statement in your code just before the implementation of the routine. For example, the following line places a routine in the DocReadFile segment:

#pragma segment DocReadFile
A #pragma segment statement remains in effect until the next such statement is encountered, so you should place a statement before each routine.

Once you have established your segment-naming strategy, you will rarely have to change the #pragma segment statements in your code, which means you won't have to compile as often. You can manage segmentation at link time with -sn directives in your MAMake file. For example, the following lines specify that the DocReadFile routine should be placed in the AReadFile segment, DocWriteFile in the AWriteFile segment, and ViewCursor in the ARes segment:

OtherSegMappings = 
-sn DocReadFile=AReadFile 
-sn DocWriteFile=AWriteFile 
-sn ViewCursor=ARes
For large applications, you may have many -sn directives, but the linker can process them efficiently. For more information on remapping segment names, see the following recipe.

Recipe--Defining a 'res!' Resource

The 'res!' resource defines those segments that should always be resident in the application heap. For more information, see "The 'res!' Resource," beginning on page 81.

To define a 'res!' resource for your 68K MacApp application, you perform these steps:

  1. Identify code that should always be resident.
  2. Map related code to the same segment.
  3. Create a 'res!' resource that lists your resident segments.

The sample code in this recipe is from the IconEdit application.

Identify Code That Should Always Be Resident

In general, you put code in a resident segment because you can't afford to have a segment load occur when you call that code. Such code might include

Map Related Code to the Same Segment

There are two convenient ways to locate code in a particular segment:

The -sn linker directive is described in "Remapping Segment Names," beginning on page 79.

Create a 'res!' Resource That Lists Resident Segments

A 'res!' resource simply lists the names of segments that should be made resident. The names correspond to those used in #pragma statements or -sn linker directives. The format is demonstrated by the IconEdit application's 'res!' resource, from the file IconEdit.r:

#if !qPowerPC
resource 'res!' (kIconEditApp,
#if qNames
   "IconEditApp",
#endif
   purgeable) {
   {  "ARes";
   };
};
#endif qPowerPC
This resource defines just one resident segment, the ARes segment. MacApp uses your application's 'res!' resource in addition to its own, which is defined in the file Memory.r.

Because MacApp remaps some of its segment names (according to information found in the file {MATools}Definitions_68K), segment names in the 'res!' resource may be different from segment names specified in the source code with #pragma statements. You can create a link map (see "Creating a Link Map," beginning on page 80) and compare it with the complete set of 'res!' resources in your application. You can also examine a 'res!' resource in ResEdit using the 'STR#' template.

#if !qPowerPC
resource 'res!' (kBaseMacApp,
#if qNames
   "BaseMacApp",
#endif
   purgeable) {
   {
      "Main";
      "MAMain";
      "ClassDescRes";
      "GConstructorRes";
      "GRes";
      "GRes1";
      "GRes2";
      "GRes3";
      "GRes4";
      "GRes5";
      "GRes6";
      "BBRes";
      "BBRes2";
      "GError";
      "AEObjSuppt";
#if qDrag
      "MADragRes";
#endif
      "MAScriptingRes";
      "SADEV";
      "INTENV";
      "STDIO";
      "STDCLIB";
      "32-bit bootstrap";
#if qPerform
      "GPerformanceTools";
#endif
   };
};
#endif qPowerPC
Note that MacApp's 'res!' resource is conditionally compiled--it is included only when the application is built to run on a 68K-based machine.

Recipe--Defining a 'seg!' Resource

MacApp uses the 'seg!' resource to store information about segmentation. For more information, see "The 'seg!' Resource," beginning on page 80.

To define a 'seg!' resource for your 68K MacApp application, you perform these steps:

  1. Identify your application segments in memory at the point of greatest memory usage.
  2. Identify the MacApp segments in memory at the same point.
  3. Create a 'seg!' resource that lists the identified segments.

The sample code in this recipe is from the IconEdit application.

Identify Segments in Memory at Greatest Memory Usage

Identifying your application's point of greatest memory usage, and the segments in memory at that point, is not a simple task. This point often occurs when printing, or when launching the application to open or print an existing document. Remember that any segment listed in a 'res!' resource is by definition resident and therefore is always part of your application's greatest memory usage.

You can use the About This Macintosh command from the Apple menu to get a rough idea of the amount of memory your application uses at various times. Utility applications available for the Macintosh provide a more detailed snapshot. You can use a debugger such as MacsBug to examine the loaded segments at a particular point in program execution.

Using your best judgment and the information provided by any available utilities, you can make a good estimate of which segments to include in your 'seg!' resource.

Identify MacApp Segments Also in Memory

You can use the same techniques described in the previous section to identify MacApp segments in memory at your application's point of greatest memory usage. They will largely fall into one of two groups:

Create a 'seg!' Resource That Lists the Segments

A 'seg!' resource simply lists the names of segments that are in memory at the point of greatest memory usage. The following is the 'seg!' resource from the IconEdit sample application:

#if !qPowerPC
resource 'seg!' (kIconEditApp,
#if qNames
   "IconEditApp",
#endif
   purgeable) {
   {  "ARes";
      "GNonRes";
      "GClipboard";
      "GClose";
      "GFile";
      "GOpen";
      "GDoCommand";
      "GSelCommand";
      "GWriteFile";
      "GReadFile";
      "GFinder";
      . . . // Some segments omitted.
      "GPrint";
      "GReadResource";
   };
};
#endif qPowerPC
Your 'seg!' resource should list all the segments identified in the two previous steps of this recipe. Your application can have more than one 'seg!' resource, so you have two options for specifying the segments your application uses at its point of greatest memory usage:

Note
MacApp automatically counts as resident any segments marked as preload.

Previous Book Contents Book Index Next

© Apple Computer, Inc.
25 JUL 1996