Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!tut.cis.ohio-state.edu!zaphod.mps.ohio-state.edu!usc!cs.utexas.edu!sun-barr!ccut!titcca!kddlab!atrpost!atr-la!alain From: alain@atr-la.atr.co.jp (Alain de Cheveigne) Newsgroups: comp.sys.mac.programmer Subject: Re: ROM Unlocks handles (was Re: How to Argue Technical Points) Message-ID: <3842@atr-la.atr.co.jp> Date: 5 Dec 89 06:49:00 GMT References: <2744@dogie.macc.wisc.edu> <3838@atr-la.atr.co.jp> <32977@ucbvax.BERKELEY.EDU> Organization: ATR International,Japan Lines: 83 In-reply-to: oster@dewey.soe.berkeley.edu's message of 4 Dec 89 02:10:25 GMT In article <32977@ucbvax.BERKELEY.EDU> oster@dewey.soe.berkeley.edu (David Phillip Oster) writes: >In article <3838@atr-la.atr.co.jp> alain@atr-la.atr.co.jp (Alain de Cheveigne) writes: >>If you use HGetState and HSetState instead, the routine leaves all handles >>just the way they were before the routine was called. The caller doesn't >>have to know how the callee does his stuff, which is the way it should be. >> >>But it seems that some ROM routines don't know it, and unlock handles >>behind one's back. A list of those would be nice. > >Alain, you have to understand "The Way od the Macintosh." The ROM >expects you to only lock down what you absolutely have to, and that for as >short a time as possible. To do otherwise is to risk running out of >usable memory because of fragmentation. I agree. I'm assuming that the duration of my (short) subroutine is a short time. Granted, this assumption might be wrong if memory is tight and some is needed during the subroutine. But if I move the handles up in the heap before locking them, it is unlikely they will get in the way of heap compaction, because the subroutine is not likely to free any space above them. >If you use a style like: > HLock(handle); > OneSystemCall(); > HUnlock(handle); >or even better: > temp = (**hand).field; > SystemCall(&temp); > (**hand).field = temp; >you'll never have to worry about the ROM unlocking things. I run into two problems with these schemes: a) The structures I use are deep. Concretely: my program uses lots of windows, which the user can create and dispose of in any order. Data is attached to each window in a relocable block, referred to by the window refCon, and that block in turn refers to other relocatable data and to another window (itself with data). So reference to a given field is done through many levels of indirection, most of them relocatable... I can't imagine locking and unlocking all this stuff at every system call, so this rules out the first scheme. b) Several of my data fields are big: text, signal arrays, and bit images used by bitmaps (yes, I'm aware of the dangers of relocating these...). I don't want to copy the data each time it is used in a system call. Or should I...? It took me lots of fumbling before I found a way to cope with handle-locking in a reasonably clean way (that can survive program modification, for example...). But I can't say it satisfies me. If someone can point a better way, please do. To make things clear, my present strategy is: a) On entry of a subroutine, save states of all handles that might be dereferenced, b)MoveHHi() and HLock() them, c) do the processing, and d) Restore handle states on exit (rather than unlock). State saving/locking and restoring is done either handle by handle, or on a window scale: a single routine locks all the data structures associated with the window, after saving their state in a state vector that is it returns. Another routine restores the states on exit. Once the structures are locked, data fields are accessed through a battery of macros that take the window as argument. No need for locking and unlocking, *except* after some system calls that unlock their argument as a side effect (the subject of my original posting). What justifies the hassle is this: I can now forget the insides of a subroutine. If I call it in some code, I don't have to remember to re-lock or unlock every handle that it might have twiddled internally (possibly as a side effect of another routine it called...). If I modify a subroutine, I don't have to go around checking for side effects. But hassle it is. Is there a better way ? Alain de Cheveigne, alain@atr-la.atr.co.jp