From: Jeff E Mandel <mandel@tmc.tulane.edu>
Subject: Re: Memory Manager-safe Deferred Tasks - A Proposal
Nntp-Posting-Host-[nntpd-26516]: mandel.anes.tulane.edu
X-Xxmessage-Id: <A702E6FF35023009@mandel.anes.tulane.edu>
X-Xxdate: Thu, 15 Oct 92 15:14:39 GMT
Organization: Tulane University School of Medicine
X-Useragent: Nuntius v1.1.1d12
Date: Thu, 15 Oct 1992 14:14:37 GMT

In article <1992Oct14.220413.10732@dartvax.dartmouth.edu> Mark R.
Valence, Mark.R.Valence@dartmouth.edu writes:
>> The problem is that of a critical section. Unless there is some secret,
>> undocumented semaphore for the Memory Manager, we create one of our own
>> by a head/tail patch for every Memory Manager routine. Basically, the
>
>
>Why not just patch NewHandle?  Then you can be guaranteed that it is
>safe to allocate memory, move the heap around, etc. because someone is
>already doing it.  You need a flag to make sure you don't re-enter your
>task scheduler, but that is easy.  What's more, you can implement the
>"Hz" functionality you originally wanted.  Here it is:
>
>NewHandle patch (note that it is a head patch):
>
> if not alreadyExecuting then
>    alreadyExecuting = true
>    if SYS bit is set then
>       theheap = SysZone
>    else
>       theheap = TheZone
>
>    scan the queued tasks, execute the
>    ones where dtHeapZone = theheap (or dtHeapZone = nil)
>
>    alreadyExecuting = false
> endif
> JumpTo(realNewHandle)
>
>end patch
>
>Remember to save ALL registers!

I believe this is not the best solution. There are many traps which move
memory, and NewHandle is only one. To make this approach work, you'd have
to head patch every trap which can move memory. Even if you wanted to do
that much patching (Which is certainly feasible), you still have the
problem that you are depending on someone to call one of the
memory-moving traps before your deferred task is delivered. What if
you're waiting for an IO request to complete? Or in a long computational
loop? the deferred task is frozen out.

>One note on this declaration:
>
>> FUNCTION DTHzInstall (dtTaskPtr: QElemPtr, dtHeapZone: THz) : OSErr;
>
>Why not declare the following, which gives an "easier" function
>declaration:
>
> DTHzElemRec = record
>   qLink: Ptr;               { standard queue field }
>   qType: integer;           { standard queue field }
>   dthzReserved: LongInt;    { for future enhancements :-) }
>   dthzProc: ProcPtr;        { pointer to the proc to execute }
>   dthzZone: THz             { the zone that this elem likes, nil for
>all }
> end;
>
> FUNCTION DTHzInstall (dthzTask: DTHzElemPtr): OSErr;

Well, I did it that way so the dtTakPtr structure could be used. If you
do it the way you suggest, then you should add a field for dtParm, so the
user can pass in a pointer to globals or such. Really, however, I'd make
the DTHzElemRec look like a DTElemRec with some extra fields, as
DTHzInstall would just install a DTTask that invoked code to determiine
whether the DTHzTask could be delivered immediately, or needed to be
moved to the special queue to await the completion of the pending memory
operations. Thus:

 DTHzElemRec = record
   qLink: Ptr;               { standard queue field }
   qType: integer;           { standard queue field }
   dthzReserved: LongInt;    { for future enhancements :-) }
   dthzProc: ProcPtr;        { filled in by  DTHzInstall}
   dthzZone: THz             { the zone that this elem will utilize }
   dthzTask: dtElemRec  { the DTTask }
 end;

>
>The problem with this implementation is that you don't know whether
>QuickDraw is in use, so you cannot draw to any ports.  But maybe all
>you want to do is allocate memory.  In general, you shouldn't use
>managers that are not re-entrant.  To use Quickdraw, you could
>similarly patch SetPort, and thereby make the executed tasks
>port-dependant.

I believe that it is a bad idea to try to have too many things going on
in "real-time". Drawing can be deferred until the app gets back to the
event loop. The user can't deal with the new data in a background app
when the foreground app is busy, so why worry about getting it to the
screen? The only thing that can't wait is stuffing data from an external
device into memory that won't be depleted under any foreseeable
circumstance, and reinitiating the read operation. 
>
>Honey?  Do you smell smoke?
I don't know, dear. But doesn't that door feel awfully warm?

Jeff