Path: utzoo!mnetor!uunet!husc6!endor!stew From: stew@endor.harvard.edu (Stew Rubenstein) Newsgroups: comp.sys.mac Subject: Re: Quickergraf bugs... Message-ID: <4260@husc6.harvard.edu> Date: 21 Mar 88 01:08:39 GMT References: <293STORKEL@RICE> <779@trwcsed.trwrb.UUCP> <2411@coherent.com> <7786@agate.BERKELEY.EDU> Sender: news@husc6.harvard.edu Reply-To: stew@endor.UUCP (Stew Rubenstein) Organization: Aiken Computation Lab Harvard, Cambridge, MA Lines: 75 In article <7786@agate.BERKELEY.EDU> lippin@ragu.UUCP (Tom Lippincott, ..ucbvax!bosco!lippin) writes: >Recently dplatt@coherent.com (Dave Platt) said: >>Apple has apparently changed the MDEF so that it can recover gracefully >>if it can't get a pixmap big enough to save the screen pixels; > >This causes a problem for me. Since there are so many ways for >out-of-memory problems to screw up the toolbox, I've responded by >writing a growzone function which, when it can't scrounge memory, will >unload most segments, put up an alert, and then longjmp back into the >main event loop. But this makes some menu choices fail even when >MenuSelect could get by without the memory. > >What I want is a way to tell if a memory request is vital or not. I >can write this into my side of the code, but I know of no way to test >this when it's a toolbox call that needs the memory. Is there one? >Will there be one eventually? (This is all grungy stuff that would be >better handled by the OS anyway, I say.) Low memory handling on the Mac is a bitch. There isn't any way to know when a memory request is critical, except to know what the toolbox needs the memory for. You have to assume that any request is critical. This is not far from the truth - memory allocation failures are handled very poorly by the toolbox. In my apps, I have routines Critical() and NonCritical(), which clear and set a flag checked by the growzone function. Then I have: INT32 MyMenuSelect(thePoint) Point thePoint; { INT32 result; NonCritical(); saveGhost = GhostWindow; /* MenuSelect will not update properly */ GhostWindow = 0; /* if you use GhostWindow. */ result = MenuSelect(thePoint); GhostWindow = saveGhost; Critical(); return result; } I also have a NewHandleNC() which I use for noncritical memory allocations in my own code. Another useful trick is to allocate a couple of buffers at the start of your program so that you have something to release when the growzone proc is called. Finally, it's important to preflight every memory request that you can. For example, before you call a routine in another segment, do a GetResource on the right CODE segment and check to see it succeeds. A failure to load a CODE segment causes an immediate system error. The GetResource won't waste much time, but you have to identify all the intersegment calls and have some way of telling what segment it's in. In MPW it's easy because it names the resources. For example: if (PreFlightCall(SEG_RotateFrob)) { RotateFrob(); UnloadSeg(RotateFrobox); } else { Alert (ALRT_notEnoughMemToRotateFrob, (FilterProc) 0); } It's especially hard to preflight QuickDraw region operations. I assume that an upper bound on the size of a region is proportional to the area of the bounding rectangle times an empirically derived fudge factor related to the likely complexity of the region. You can also use MapRgn to do the operation on a scaled-down region first, as suggested in Inside Macintosh, but I find this too time consuming for most purposes. Stew Rubenstein Cambridge Scientific Computing, Inc. UUCPnet: seismo!harvard!rubenstein CompuServe: 76525,421 Internet: rubenstein@harvard.harvard.edu MCIMail: CSC