ferdie@coyote.datalog.com (fred jarvis) (04/05/91)
I want to use a list structure in a Windows application.
Typically, something like
typedef struct {
datatype *data;
listnode *next;
} listnode;
would be used, with each node dynamically allocated.
But in Windows, you're supposed to use GlobalAlloc or LocalAlloc,
which return handles, not pointers, then using GlobalLock &
GlobalUnlock or LocalLock etc. to get the pointers for only as long
as you need access.
If listnode contains handles, rather than pointers, each time a
node is referenced, calls to GlobalLock & ..Unlock (or LocalLock...)
must be made, which seems inefficient to me.
I know LocalAlloc returns a pointer if called with the
LMEM_FIXED flag, but this is discouraged by the higher powers
(e.g. Petzold). So what is the best approach to take (besides
going back to DOS) ?
Fred Jarvis ferdie@coyote.datalog.com
gpsteffl@sunee.waterloo.edu (Glenn Steffler) (04/06/91)
In article <e2BXZ1w163w@coyote.datalog.com> ferdie@coyote.datalog.com (fred jarvis) writes: > I want to use a list structure in a Windows application. >Typically, something like > typedef struct { > datatype *data; > listnode *next; > } listnode; >would be used, with each node dynamically allocated. Obviously this is a no-no in Windows, as you must allocate crap loads of pointers (ie. handles, then locked). This would eat up the local handle table to the point where you run out of local heap space. The same issue faces you with global memory handles. > If listnode contains handles, rather than pointers, each time a >node is referenced, calls to GlobalLock & ..Unlock (or LocalLock...) >must be made, which seems inefficient to me. Can't be done in an independant fashion. (not portable eh!?) > I know LocalAlloc returns a pointer if called with the >LMEM_FIXED flag, but this is discouraged by the higher powers >(e.g. Petzold). So what is the best approach to take (besides >going back to DOS) ? As I have said in three or four posts the last four months: Gold Disks new animation package for M Windows required several thousand records and has (possibly) hundreds of link lists to keep track of the play lists for the animations, and the resource lists of the bitmaps/sounds/midi etc data. The only good solution was to write my own custom memory management stuff which allocates global memory locks it, and then divides said memory into bite sized (sorry for the pun) chunks for use in link lists. Since protect mode allows memory to appear fixed logically while physically moving around we are totally Windows friendly. However, we wouldn't run very well in real mode or with expanded (*EMS) memory as the locked memory segment would impeed normal Windows memory compaction etc. Once the block has been fully divided, either re-size it bigger or if too big (>32k wastes cycles when moving memory in standard mode) simply allocate another global block and continue the concept. Thus, my solution is fair, adequate and seems to leave Windows with plenty of memory management leeway in protect mode. (Yea, like what fool would create animations in real mode?? -serious) Besides allocating blocks with global alloc creates a selector table entry (descriptor) which must be cached by the processor every time a new selector is accessed. Trust me...this can slow down the processor quite a bit when skipping thru a link list. > Fred Jarvis ferdie@coyote.datalog.com I realize this solution doesn't make anything easy, as you basically have to write your own malloc/free routines, but hey, what are you using your first year data structures course knowledge on anyway? :-) -- Windows Sumo Wrestler "Bo doesn't know software" - George Brett --(Windows 3.0, a combination of modern moodring technology and voodoo)-- "I guess she had a way, of making every night seem bright as day" `I Don't Believe In Love` -Queensryche (Oper. Mindcrime) Glenn Steffler
tonyg@polari.UUCP (Tony Gosling) (04/10/91)
In article <1991Apr5.205519.29757@sunee.waterloo.edu>, gpsteffl@sunee.waterloo.edu (Glenn Steffler) writes: > In article <e2BXZ1w163w@coyote.datalog.com> ferdie@coyote.datalog.com (fred jarvis) writes: > > I want to use a list structure in a Windows application. > >Typically, something like > > typedef struct { > > datatype *data; > > listnode *next; > > } listnode; > >would be used, with each node dynamically allocated. > > Obviously this is a no-no in Windows, as you must allocate crap loads > of pointers (ie. handles, then locked). This would eat up the local handle > table to the point where you run out of local heap space. The same > issue faces you with global memory handles. [The rest of Glenns answer deleted] Glenn has given a good description of the issues involved here. Another way you can do this is to create a local heap in a separate block of memory allocated by GlobalAlloc. LocalInit will create a local heap in that block for you. Using such a block is not straightforward, you need to set DS to the segment(selector) of the block before calling any Local routines. For example: hHeap = GlobalAlloc(GMEM_MOVEABLE, 4096L); segHeap = HIWORD(GlobalLock(hHeap)); LocalInit(segHeap,16,4095); To alloc from this heap: _asm mov SaveDS, ds; _asm mov ds, segHeap; hlocal = LocalAlloc(LMEM_FIXED, wBytes); _asm mov ds, SaveDS; (... far *)(hHeap<<16 + hlocal) will point to this object. Using Microsoft's C6 based pointers would make referencing objects in this heap easy. A couple of notes: When calling LocalInit, DO NOT use the first 16 bytes of the object. The End parameter to LocalIinit will be one less than the size of the block you allocated. Apologies for any syntax errors and the lack of typing in my example. The SaveDS, wBytes and hlocal variables must be local ie. stack variables. Tony Gosling.
jta@locus.com (JT Anderson) (04/10/91)
I have not tried this, but someone who needs to sub-allocate from a block of memory obtained by GlobalAlloc may want to investigate and report back. There are functions in MSC 6.0 for allocating from based heaps. These functions allow you to manage several heap segments. They may be just the ticket for managing a block of memory allocated by GlobalAlloc. Take a look at _heapadd, _bmalloc, _bfree, etc. You will probably need to cheat a little, and the run time library source might be quite helpful, but not necessary, in determining how these things work.
al@well.sf.ca.us (Alfred Fontes) (04/13/91)
>Another way you can do this is to create a local heap in a separate >block of memory allocated by GlobalAlloc. LocalInit will create >a local heap in that block for you. The January, 1991 issue of Microsoft Systems Journal has some source code in it for precisely this technique. You can download it from one of the BBS's that keep the source code from the magazine.
pcb@basin06.cacs.usl.edu (Peter C. Bahrs) (04/15/91)
In article <24183@well.sf.ca.us> al@well.sf.ca.us (Alfred Fontes) writes: >>Another way you can do this is to create a local heap in a separate >>block of memory allocated by GlobalAlloc. LocalInit will create >>a local heap in that block for you. > >The January, 1991 issue of Microsoft Systems Journal has some source >code in it for precisely this technique. You can download it >from one of the BBS's that keep the source code from the magazine. I don't have access to the BBS or even know how to use it. Can someone mail a copy of the source if you have it online? Or post it to cica. Thanks pcb@basin04.cacs.usl.edu
gpsteffl@sunee.waterloo.edu (Glenn Steffler) (04/16/91)
Tony G sez, and I quoteth: >Another way you can do this is to create a local heap in a separate >block of memory allocated by GlobalAlloc. LocalInit will create >a local heap in that block for you. Good idea for small (and boy do I mean small) linked list. But I am dealing with something over 150k of list memory for a long (say five minute) movie! There is no easy way of determining which list element belongs to which global block unless you allocate the memory such that it doesn't matter, and treat the 32 pointers just like you would in Unix et all. I also wrote a small memory management function set which doesn't allocate global blocks and split the memory, but allocates a SINGLE GLOBAL block for every list item! This is a great way to debug code, because it makes sure that any warry accesses to the memory will be trapped in protect mode. I also made sure the pointer was aligned in the global block such that no matter how many "extra" bytes windows afforded me on the global alloc call (found via GlobalSize) I always return a pointer whose end position (from length given in my_malloc call) will produce a GP fault if even ONE byte more is read or written to the block! Saved my butt couple o' times... :-) Anyway, just my little ol' ramblings. -- Windows Sumo Wrestler "Bo doesn't know software" - George Brett --(Windows 3.0, a combination of modern moodring technology and voodoo)-- "I guess she had a way, of making every night seem bright as day" `I Don't Believe In Love` -Queensryche (Oper. Mindcrime) Glenn Steffler