Switcher hints


Author: Mike Ward
Date: 17 Apr 1985 11:46 pm

A Software Developer's Guide to Switcher
Andy Hertzfeld   9 Apr 85
   The Macintosh Application Switcher creates a dynamic new software
   environment for the 512K (or larger) Macintosh, allowing multiple
   application programs to reside simultaneously in memory and
   providing a way to switch between them very quickly.  The
   Switcher tries to support every Macintosh application, but
   the interface between a program and its environment is very
   complex, and Switcher necessarily disturbs this delicate balance,
   so some programs are not compatible with it.  This document
   is intended for an audience of Macintosh software developers
   and will provide suggestions and hints that will help your
   application to get the most out of the Switcher environment.

  The most recent version of the Switcher is version 2.0, the
   beta release.  Included with the release are new versions
   of the Macsbug debugger that are compatible with the Switcher.
   Earlier versions of Macsbug had a bug that made them not work
   with Switcher, so be sure to use these new versions when testing
   your applications out with Switcher.  When you find that your
   application doesn't work properly with Switcher, please try
   to pinpoint the difficulty as precisely as possible when reporting
   the bug;  bugs can be reported to Apple, on MAUG/Compuserve
   (my number is 70167,3430) or directly to me at (415) 322-8696.

  One source of developer confusion is caused by the way the
   Switcher fudges memory size statistics. It turns out you have
   to allocate a 96K partition for an application to have approximately
   the same amount of memory it has on a 128K Mac.   To avoid
   confusion for the typical user, the Switcher adds 32K to the
   size of a partition before displaying it.  Thus partition
   sizes are "normalized" to the well-known 128K Mac;  for example,
   a partition that's displayed as 256K actually only has 224K
   allocated to it.

  The Switcher knows how much memory to allocate to a given
   program by inspecting the "SIZE -1" resource attached to the
   program file.  The Switcher is capable of generating its own
   SIZE blocks using the Configure command, but it would be very
   nice if new applications could come "pre-configured" for their
   own unique memory requirements and other properties.  The
   size block is 10 bytes long; there is a flags word followed
   by 2 long integers.  The first long integer is the recommended
   size of the partition, followed by the minimum size.  The
   values are 32K less than the virtual partition size (i.e.
   96K for a 128K partition).  Currently, only the high two bits
   of the flags word are defined.  Bit 15 means "save screen"
   and bit 14 means "suspend/resume" events. (see below).  Unassigned
   bits should be kept 0 for future compatibility.

  While working at Apple, I had the opportunity to watch a number
   of fairly complicated Macintosh applications go through their
   final debugging cycles.  The most time-consuming and difficult
   part of this process is what you might call "memory tuning",
   which is dealing with various out-of-memory situations and
   with memory fragmentation.  Typically, an application is tested
   and tuned to run on both 128K and 512K Macintoshes.  However,
   the Switcher environment supports variable-sized partitions,
   so many more memory situations become possible (i.e., a 256K
   Mac).  The biggest problem most applications have working
   smoothly with the Switcher is that they were tuned for 128K
   or 512K, and sometimes are freaked out by something in between,
   because they make decisions like "it's not 128 so it must
   be 512".  Switcher-friendly applications should test memory
   to see how much is available and be able to deal with a wide
   range of memory sizes.  The best way to size memory initially
   is to grow the heapZone out to its maximum size by requesting
   an enormous block, and then execute a "FreeMem" or "MaxMem"
   call.  After initialization, the best way to determine if
   a certain amount of memory is currently available is to use
   the "ReserveMem" call.  Switcher also sets up the low-memory
   location "MemTop" with the size of the current partition normalized
   to a 128K Mac, but it is not recommeded that memory-sizing
   decisions be based on that.  Make sure you never make any
   assumptions about how much memory is available by looking
   at absolute addresses, as you don't know where you are going
   to be loaded.

  Many applications have a need to create temporary disk files
   using a filename generated by the application like "Edit.Scratch"
   or "Paint1".  Since the Switcher environment supports running
   the same application twice, file name conflicts are possible.
   A Switcher-friendly application should never used a hard-wired
   name for a temp file; instead,  it should make up one using
   a random number or the time of day clock, so the names will
   not conflict if its running concurrently in two different
   partitions. For example, instead of using "Paint1", use "Paint03:12:35".

  Switcher switches contexts only when an application executes
   a "GetNextEvent" call, so applications never have to fear
   being suspended when they are engaged in some time-critical
   activity.  To be compatible with Switcher, your application
   must call GetNextEvent periodically, as most applications
   do. To be able to cut and paste under Switcher, your application
   must support desk accessories by maintaining an Apple menu,
   and supporting cutting and pasting with desk accesories.  
   This is because Switcher fools your application into coercing
   the clipBoard into global format by making think its cutting
   or pasting into a desk accessory.   Watch out for an entry
   in the desk accessory menu that isn't really a desk accessory.
   See the discussion below on suspend/resume events for further
   information on the "desk-accessory charade" .

  To make most effective use of memory, the Switcher supports
   an option where it will not save the bits of an application's
   screen when it switches.  If this option is in effect, the
   program must be able to respond to update events to regenerate
   the screen.  Thus, switcher-friendly programs should be prepared
   to handle update events.

  Another class of Switcher incompatibilities is caused by asynchronous
   I/O. It is possible for a suspended application to receive
   control via a completion routine after its been switched out
   .  Completion  routines must be very careful about referencing
   low memory and globals, as they might have been swapped out
   and A5 is probably differentOnique for performing Switcher-friendly
   async I/O  is to pass A5 at the end of the I/O parameter block,
   so your completion routine (which is passed the parameter
   block) can reference globals.  This is only relevant to non-file
   I/O, as the Switcher refuses to switch if the file system
   is busy.  Also, the Switcher suspends any vertical retrace
   tasks executing in a given partition when the main application
   is suspended, so your vertical retrace tasks don't have to
   worry about this.

  Another potential danger area for Switcher compatibility involves
   timing.  In the Switcher environment, it is possible for an
   application to be suspended for an indefinite period.  Some
   applications use "Ticks" for relative timing; they must be
   careful to use 32-bit compares and arithmetic as Switcher
   makes it possible for more than 64K ticks to have elapsed
   since the last time you looked at it.

  Even though the Switcher is intended to work "behind the back"
   of most applications, it includes some features that allow
   newly written programs to perform very smoothly with it.  
   For example, if an application knew it was about to be suspended,
   it could clean up its act by killing I/O tasks, etc.  To deal
   with this, the Switcher provides optional "suspend/resume"
   events.  A suspend event means that the next time you call
   GetNextEvent, you will be suspended.  A resume event is the
   first event you get back after you've been re-activated following
   a suspension.  Suspend and resume events are both reported
   as event 15  (formerly an application-defined event).  The
   high byte of the message field is set to 01 to indicate that
   its a suspend/resume event (eventually event 15 will be used
   for other purposes as well).  The lowest bit of the message
   field (bit 0) is clear if its a suspend event and set if its
   a resume event. The next bit up (bit 1) is set if clipboard
   coercion is required.  The Switcher uses bit 14 of the flags
   word in the SIZE record to indicate if a program should receive
   suspend/resume events.  If this bit is set, the Switcher won't
   put on the desk accessory charade for clipboard coercion,
   as it assumes that the application is converting the clipboard
   when requested to in the suspend/resume event.

  An even more exciting area is that of "interlocking" applications
   that run fine by themselves but are ultra-integrated when
   run together under the Switcher.  Applications can find out
   the global picture by inspecting  Switcher globals.  Switcher
   globals are accessed through a low-memory pointer kept at
   address $282.  If the pointer kept there is -1 or 0, it means
   that the application is not currently running under the Switcher.
   Otherwise, its a pointer to a public table of Switcher global
   variables.  The first 8 longWords in the table is a list of
   pointers to the base of all currently active applications,
   or zero if no application is present in a given slot.  By
   inspecting this table, applications can determine what other
   applications they are coexisting with and where they are located.
   Apple will eventually provide complete documentation on effectively
   using this "world" table, as well as detailing some other
   useful Switcher globals.

  All in all, it is amazing to me how many programs do run properly
   under the Switcher.  Most developers should not have to worry
   or understand all of the stuff discussed here;  ordinary applications
   usually run just fine.  It has been fun working on the Switcher.
   To diagnose various crashes, I had to trace through the guts
   of lots of very different applications.  Countless features
   and strategy shifts were implemented to support this or that
   application.  As a designer of the Mac system, I'm one of
   the very few who never had the experience of trying to learn
   how it works.  In a way, developing the Switcher was the application
   programmer's revenge for that experience.  It certainly gave
   me a new appreciation for our strange and wonderful software

Switcher hints
117 Apr 1985 11:46 pmMike Ward