home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!dtix!darwin.sura.net!Sirius.dfn.de!news.uni-stuttgart.de!rz.uni-karlsruhe.de!stepsun.uni-kl.de!oinone.kit.uni-kl.de!sold
- From: sold@kit.uni-kl.de (Christoph Sold)
- Newsgroups: comp.sys.mac.programmer
- Subject: Re: Help with piggybacking data on window records
- Message-ID: <sold.48.713823213@kit.uni-kl.de>
- Date: 14 Aug 92 20:13:33 GMT
- References: <1992Aug10.223248.3217@ucsvc.ucs.unimelb.edu.au>
- Sender: news@rhrk.uni-kl.de
- Organization: Universitaet Kaiserslautern
- Lines: 186
-
- In article <1992Aug10.223248.3217@ucsvc.ucs.unimelb.edu.au> u2005681@ucsvc.ucs.unimelb.edu.au writes:
- >Subject: Help with piggybacking data on window records
- >From: u2005681@ucsvc.ucs.unimelb.edu.au
- >Date: 10 Aug 92 12:32:48 GMT
- >Hi People,
- >This is my first application so don't be too harsh.
- >I'm trying to piggyback data on a window record so I can keep
- >track of pop-up menus and icon buttons in a multi-window
- >application.
- >I store my handles in a struct called winPrivate.
- >When I create a new window I do the following:
- >
- >wp = GetNewWindow(rMainWindow, (Ptr)0L, (WindowPtr)-1);
- >myPrivate = NewHandleClear(sizeof(winPrivate));
- >SetWRefCon(wp, (long)myPrivate);
- >
- >This seem to allocate the space required (I check if
- >the allocation fails).
- >
- >When trying to retrieve the data in a routine I do the
- >following:
- >
- >void Routine(WindowPtr wp, .....);
- >{
- > winPrivateHndl dataHandle;
- > short x;
- > Rect theRect;
- >
- > dataHandle = (winPrivateHndl) GetWRefCon(wp);
- > HLock(dataHandle);
- > .
- > .
- > x = (*dataHandle)->x1; /* for example */
- > DrawPicture((*dataHandle)->thePicHandle, &theRect);
- > .
- > .
- > .
- > HUnlock(dataHandle);
- >}
- >
- >I seem to be able to retrieve data this way but I am losing
- >memory by the kilobyte. Every time I call a routine that
- >accesses the piggyback data, I seem to end up with a
- >locked memory block (even though I UNLOCK it when I leave
- >the routine. When I close the window and dispose of all my
- >handles, I don't seem to regain any memory!
- >Can anybody help me with this problem?
- >Am I doing the piggyback thing correctly?
- >Am I accessing the piggybacked data correctly?
- >Thanks in advance for any suggestions, I am at the end of
- >my wisdom.
- >
- >Chris Hofflin
-
-
- Chris,
-
- here the two ways to piggyback data into any (handle|pointer)-referenced
- block:
-
- 1) packing private data onto the back of the OS record
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- The big idea is the OS wants n bytes, at n+1 bytes you can do what you want.
- Here is a picture of this memory layout:
-
- byte 0 +-----------+
- |OS record |
- | |
- byte n +-----------+
- byte n+1|your data |
- |... |
-
- | |
- +-----------+
-
- To do this, you allocate _one_ memory block, and use a pointer|handle to it
- as you wish. In pascal, this is define this way:
-
- TYPE
- WindowRecord = Record
- {some fields here}
- END; {WindowRecord}
-
- PrivateRecord = Record
- {more fields here}
- END; {PrivateRecord}
-
- PiggyPack = Record
- w: WindowRecord;
- p: PrivateRecord;
- END; {PiggyPack}
-
- Now you can pass a pointer to PiggyPack equivalent to a pointer to
- WindowRecord, since both start at the same location.
-
- Unfortunately, this will crash as soon as apple chooses to add more fields
- to a (Window)Record -- since your private data is in the place new fields
- will be allocated. Method 1: bad way. Don't use it, until you have written
- warranty from apple the os record will never change.
-
- 2) packing a reference to your data in a useful place
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Fortunately, nearly every os record has a "for your convenience"-field,
- often named "refCon". Just four bytes long, this is enough to catch a
- pointer or handle. It is also the way you choose (some kudos for this. well
- done!). It looks in memory this way:
-
- +------------+
- | os record |
- | ... | +------------+
- |"refCon" ----->|private data|
- +------------+ |... |
- +------------+
- To do this one, you have to manage your memory careful: The operating system
- knows _nothing_ about the handle|pointer in the refCon field.
- Error #1 is to de-allocate the os record without deallocating the private
- data first: This is a (major) memory leak, since the private block is still
- in the heap, and is referenced by nothing else. No way to recover it.
- Error #2 is to de-allocate the private data without setting it's reference
- variable to NULL|NIL. This way you can reference a previously freed block --
- possibly with some valid data in it. But this block will be overwritten --
- sooner or later.
- Knowing this two error causes, we can define the only way to do this sort of
- pig(gy)-bag. Again, in Pascal:
-
- TYPE
- WindowRecord = RECORD
- {some fields here}
- refCon: LongInt; {four bytes apple never uses--behold the Coom
- Toolbox}
- END; {WindowRecord}
- WindowPtr = ^WindowRecord;
-
- PrivateRecord = RECORD
- {some private data here}
- END; {PrivateRecord}
- PrivatePtr = ^PrivateRecord;
-
- VAR
- w: WindowPtr;
- p: PrivatePtr;
-
- {Allocation}
-
- w := NewPtr(sizeOf(WindowRecord)); {allocate a window record}
- w.refCon := NIL; {just to be sure, since there is no private data yet}
- {.. do something with the window record, e.g.:}
- wp := GetNewWindow(kMyWindow, w, Ptr(-1));
-
- {...}
- p = NewPtr(sizeOf(PrivateRecord));{allocate a private record}
- w.refCon := LongInt(p); {now refCon points to your private data}
- {alternatively, use for WindowRecords only}
- SetWRefCon(wp, LongInt(p));
-
- {Deallocation}
- p := w.refCon;
- {for WindowRecords only, you can use}
- p := GetWRefCon(wp);
- ReleasePtr(p);
- w.refCon := NIL; {*** important! *** see error #2}
- {alternatively, for window records only}
- SetWRefCon(wp, 0); {since nil is 0}
-
- {...}
- CloseWindow(wp);
-
-
-
- OK, thats the whole point. Additionally, I suggest to switch from C to
- either C++ or Pascal, since both of these langauages provide strong
- typechecking. This is essential for a beginner, since the compiler will
- catch much more of typcal beginners typos and errors. Also recommended is
- Inside Macintosh, Memory management chapters (for the theoretical
- background), as well as the Programmers FAQ posted periodically here.
-
- Hope this helped a little.
-
- -Christoph
-
- Christoph P. Sold CATS Software GmbH
- Mussbacher Landstr.2
- W-6730 Neustadt (Weinstrasse)
- ger.xse0035@applelink.apple.com Germany
-
- "If an apple is fun, what the heck is an appletree?"
-