Path: utzoo!attcan!uunet!hoptoad!tim From: tim@hoptoad.uucp (Tim Maroney) Newsgroups: comp.sys.mac.programmer Subject: Re: HLock Message-ID: <9313@hoptoad.uucp> Date: 17 Dec 89 03:36:16 GMT References: <3331@hub.UUCP> Reply-To: tim@hoptoad.UUCP (Tim Maroney) Organization: Eclectic Software, San Francisco Lines: 65 In article <3331@hub.UUCP> 6500stom@hub.UUCP writes: >> I know this has been discussed before, but could someone tell me when >> it is necessary to use HLock? If i have a handle within a CDEF do i need >> to do so? What if i only access the handle thru a pointer, i.e. : >> >> ControlPtr cp; >> cp = *theControl; >> if (cp->contrlRect ...... and so on....... > >It doesn't matter whether you dereference it or not in C. You might >as well have done (**theControl).contrlRect instead of cp->contrlRect. Sort of. I would never do this, and I strongly recommend against it. As soon as anything happens which could move memory, cp becomes an invalid pointer, and has to be refreshed from theControl. It would be awfully easy to forget this; it's asking for errors which wouldn't happen if you always used (*theControl)-> instead of cp-> . So, when do you need to lock down handles? Very rarely. You cited the main case, Josh: >The way to remember if you need to lock your handle is if you pass >a field in the handle to any procedure that might move memory--even >if its one of your own routines in a different segment. >For example, if you do >RectRgn(myRgn, (**theControl).contrlRect) you need to lock theControl >down because RectRgn might move the handle before its done with the >contrlRect. Another case, which some people may remember I posted an ill-considered flame about a few months ago, is: (*marsup)->wombat = NewHandle(WOMBAT_SIZE); The compiler is free to evaluate the address of the left-hand side before it performs the right-hand side. If NewHandle moves memory, then its return value will be assigned into outer space. However, I don't like to lock handles when it can be easily avoided. I would do your case without locking by using a temp variable, and the same for my case. Rect r; r = (*theControl)->contrlRect; RectRgn(myRgn, &r); and Handle h = NewHandle(WOMBAT_SIZE); (*marsup)->wombat = h; Slightly more stack overhead, but you avoid trap overhead for locking and unlocking, and also avoid all the state-restoration hassles that have been mentioned lately here. One final point: heap scramble mode in a debugger, while very slow, is excellent at discovering when you have not respected handle dereferencing issues. It is a good idea to do as complete a test run as you can stand under heap scramble every few weeks or even days. -- Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com "Our newest idol, the Superman, celebrating the death of godhead, may be younger than the hills; but he is as old as the shepherds." - Shaw, "On Diabolonian Ethics"