Important: The information in this document is obsolete and should not be used for new development.
Using Application Global Variables in Tasks
When a Time Manager task executes, the A5 world of the application that installed the corresponding task record into the Time Manager queue might not be valid (for example, the task might execute at interrupt time when that application is not the current application). If so, an attempt to read the application's global variables returns erroneous results because the A5 register points to the application global variables of some other application. When a Time Manager task uses an application's global variables, you must ensure that register A5 contains the address of the boundary between the application global variables and the application parameters of the application that launched it. You must also restore register A5 to its original value before the task exits.It is relatively straightforward to read the current value of the A5 register when a Time Manager task begins to execute (using the
SetCurrentA5
function) and to restore it before exiting (using theSetA5
function). It is more complicated, however, to pass to a Time Manager task the value to which it should set A5 before accessing its application's global variables. The problem is that neither the original nor the extended Time Manager task record contains an unused field in which your application could pass this information to the task. The situation here is unlike the situation with Notification Manager tasks or Sound Manager callback routines (both of which provide an easy way to pass the address of the application's A5 world to the task), but it is similar to the situation with vertical retrace tasks.
One way to gain access to the global variables of the application that launched a Time Manager task is to pass to
- Note
- For a more detailed discussion of setting and restoring your application's A5 world, see the chapter "Memory Management Utilities" in Inside Macintosh: Memory. ·
InsTime
(orInsXTime
) andPrimeTime
the address of a structure, the first segment of which is simply the corresponding Time Manager task record and the remaining segment of which contains the address of the application's A5 world. For example, you can define a new data structure, a Time Manager information record, as follows:
TYPE TMInfo = {Time Manager information record} RECORD myTMTask: TMTask; {original and revised TM task record} tmRefCon: LongInt; {space to pass address of A5 world} END; TMInfoPtr = ^TMInfo;Then you can install and activate your Time Manager task as illustrated in Listing 3-2. The global variable
- Note
- The
TMInfo
record defined above is intended for use with the extended Time Manager. ·gTMInfo
is an information record of typeTMInfo
.Listing 3-2 Passing the address of the application's A5 world to a Time Manager task
PROCEDURE InstallTMTask; CONST kDelay = 2000; {delay value} BEGIN gTMInfo.myTMTask.tmAddr := @MyTask; {get address of task} gTMInfo.myTMTask.tmWakeUp := 0; {initialize tmWakeUp} gTMInfo.myTMTask.tmReserved := 0; {initialize tmReserved} gTMInfo.tmRefCon := SetCurrentA5; {store address of A5 } { world} InsTime(@gTMInfo); {install the info record} PrimeTime(@gTMInfo, kDelay); {activate the info record} END;With the revised and extended Time Managers, the task is called with register A1 containing the address passed toInsTime
(orInsXTime
) andPrimeTime
. Thus, the Time Manager task simply needs to retrieve theTMInfo
record and extract the appropriate value of the application's A5 world. Listing 3-3 illustrates a task definition for this purpose.Listing 3-3 Defining a Time Manager task that can manipulate global variables
FUNCTION GetTMInfo: TMInfoPtr; INLINE $2E89; {MOVE.L A1,(SP)} PROCEDURE MyTask; VAR oldA5: LongInt; {A5 when task is called} recPtr: TMInfoPtr; BEGIN recPtr := GetTMInfo; {first get your record} oldA5 := SetA5(recPtr^.tmRefCon); {set A5 to app's A5 world} {Do something with the application's globals here.} oldA5 := SetA5(oldA5); {restore original A5 } { and ignore result} END;This technique works primarily because the revised and extended Time Managers do not care if the record whose address is passed toInsTime
(orInsXTime
) andPrimeTime
is larger than expected. If you use this technique, however, be sure to retrieve the address of the task record from register A1 as soon as you enter the Time Manager task (because some compilers generate code that uses registers A0 and A1 to dereference structures).
- IMPORTANT
- You cannot use the technique illustrated in Listing 3-3 with the original Time Manager because it does not pass the address of the task record in register A1. To gain access to your application's global variables when using the original Time Manager, you would need to store your application's A5 value in one of the application's code segments (in particular, in the code segment that contains the Time Manager task). This technique involves the use of self-modifying code segments and is not in general recommended. Applications that attempt to modify their own
'CODE'
resources may crash in operating environments (for example, A/UX) that restrict an application's access to its own code segments. ·