[comp.sys.mac.programmer] Question on Handle locking example

uucibg@sw1e.UUCP (3929] Brian Gilstrap) (01/25/89)

I'm not clear on why function 'a' below would die.  This was posted recently
as an example of how not to code.  I'm sure I'm missing something extremely
obvious (it's late...), but please explain....

>a()
>{	
>	HLock(h);
>	b(h);
>	*h->x = ...	/* this would not survive a heap scramble */
>	HUnlock(h);
>}

Thanks,
Brian R. Gilstrap                          Southwestern Bell Telephone
One Bell Center Rm 17-G-4                  ...!ames!killer!texbell!sw1e!uucibg
St. Louis, MO 63101                        ...!bellcore!texbell!sw1e!uucibg
(314) 235-3929
#include <std_disclaimers.h>

thecloud@pnet06.cts.com (Ken Mcleod) (01/28/89)

 uucibg@sw1e.UUCP ([5-3929] Brian Gilstrap) writes:
>
>I'm not clear on why function 'a' below would die.  This was posted recently
>as an example of how not to code.  I'm sure I'm missing something extremely
>obvious (it's late...), but please explain....

>a()
>{
>       HLock(h);
>       b(h);
>       *h->x = ...     /* this would not survive a heap scramble */
>       HUnlock(h);
>}

  The 'obvious' portion was in function 'b', which unlocked the handle 'h'
before returning. Therefore, at the time h is dereferenced, the handle
is unlocked! There's nothing wrong with function 'a' as posted above,
which was the whole moral of this story: watch your HLock's and HUnlock's
very carefully!

==========    .......    ===================================   ============
Ken McLeod   :.     .:   UUCP: {crash uunet}!pnet06!thecloud   "They mean
----------  :::.. ..:::  InterNet: thecloud@pnet06.cts.com      to win
!(C)1988       ////            or thecloud@dhw68k.cts.com       Wimbledon!"

rob@munnari.oz (Robert Wallen) (01/29/89)

In article <1219@sw1e.UUCP> uucibg@sw1e.UUCP ([5-3929] Brian Gilstrap) writes:
>I'm not clear on why function 'a' below would die.  This was posted recently
>as an example of how not to code.  I'm sure I'm missing something extremely
>obvious (it's late...), but please explain....
> [function a() deleted brevity]

The original posting also showed function b() which locked the handle it was
passed on entry, and unlocked it on exit.  Obviously, a() assumed that the
handle was still locked even though it was not.

Yes, its not as big a problem in C since the handle was being fully 
dereferenced each time.  However, if at any stage, a() had assumed h was locked
it would break.

Perhaps it becomes more apparent if I do this
a()
{
    Handle h;
    Ptr p;

    HLock(h);
    p = *h;         /* dereference for faster access */
    b(h);
    *p = ...        /* oops. we assumed that p would still be good because h */
    HUnlock(h);     /* was locked. since b unlocked it, it aint 8-( */
}
    
#ifdef ACCEPTING_FLAMES

Boy oh boy do these things get confused when you only post part of the original
The original posting did say 'its more of a problem in Pascal than C'.
The original posting did say 'code like this ... '
It also showed b() without which no-one could say why a() was not brilliant.

#endif

Hope that helps.  I know Jeff sometimes summarises what he is saying 'a little
too much'. Believe me, its better to shut him up quick than to let him rave
for hours 8-)  [ Hi Jeff ].

oster@dewey.soe.berkeley.edu (David Phillip Oster) (01/29/89)

In article <1219@sw1e.UUCP> uucibg@sw1e.UUCP ([5-3929] Brian Gilstrap) writes:
>I'm not clear on why function 'a' below would die.  This was posted recently
>as an example of how not to code.  I'm sure I'm missing something extremely
>obvious (it's late...), but please explain....
>
>>a()
>>{	
>>	HLock(h);
>>	b(h);
>>	*h->x = ...	/* this would not survive a heap scramble */
>>	HUnlock(h);
>>}

B was defined as:
b(h)Handle h;{
	HLock(h);
	...
	HUnlock(h);
}
so the bad line in a gets executed with h already unlocked. One fix is to
write:
b(h)Handle h;{
	char state;
	state = HGetState(h);
	HLock(h);
	...
	HSetState(h);
}

Note: before you start coding with this style, disassemble the glue your
system uses for HGetState(). If it directly calls the system trap, you are
going to have to use:

unsigned char MyHGetState(h)Handle h;{
	if(world.machineType > envMac)
		return HGetState(h);
	else
		return *((unsigned char *) h);
}
and similarly for HSetState, as the code says, classic macs don't have
this trap.  (You'll have to do a SysEnvirons(1, &world); in your Init()
routine.)
}

--- David Phillip Oster            --"When we replace the mouse with a pen,
Arpa: oster@dewey.soe.berkeley.edu --3 button mouse fans will need saxophone
Uucp: {uwvax,decvax}!ucbvax!oster%dewey.soe.berkeley.edu --lessons." - Gasee