GMEM.C
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:10k
源码类别:
Windows编程
开发平台:
Visual C++
- /******************************************************************************
- * This is a part of the Microsoft Source Code Samples.
- * Copyright (C) 1993-1997 Microsoft Corporation.
- * All rights reserved.
- * This source code is only intended as a supplement to
- * Microsoft Development Tools and/or WinHelp documentation.
- * See these sources for detailed information regarding the
- * Microsoft samples programs.
- ******************************************************************************/
- /****************************** Module Header *******************************
- * Module Name: GMEM.C
- *
- * Memory utility functions.
- *
- * Functions:
- *
- * gmem_panic()
- * gmem_init()
- * gmem_get()
- * gmem_free()
- * gmem_freeall()
- *
- * Comments:
- *
- * Global heap functions - allocate and free many small
- * pieces of memory by calling global alloc for large pieces
- * and breaking them up. A heap contains a critical section, so
- * multiple simultaneous calls to gmem_get and gmem_free will be
- * protected.
- *
- * gmem_freeall should not be called until all other users have finished
- * with the heap.
- *
- * Out-of-memory is not something we regard as normal.
- * If we cannot allocate memory - we put up an abort-retry-ignore
- * error, and only return from the function if the user selects ignore.
- *
- ****************************************************************************/
- #include <windows.h>
- #include <memory.h>
- #include "gutils.h"
- #include "gutilsrc.h"
- int gmem_panic(void);
- /* ensure BLKSIZE is multiple of sizeof(DWORD) */
- #define BLKSIZE 64 /* blk size in bytes */
- #define ALLOCSIZE 32768
- #define NBLKS (ALLOCSIZE / BLKSIZE)
- #define MAPSIZE (NBLKS / 8)
- #define MAPLONGS (MAPSIZE / sizeof(DWORD))
- #define TO_BLKS(x) (((x) + BLKSIZE - 1) / BLKSIZE)
- typedef struct seghdr {
- HANDLE hseg;
- CRITICAL_SECTION critsec;
- struct seghdr FAR * pnext;
- long nblocks;
- DWORD segmap[MAPLONGS];
- } SEGHDR, FAR * SEGHDRP;
- /* anything above this size, we alloc directly from global heap */
- #define MAXGALLOC 20000
- /***************************************************************************
- * Function: gmem_init
- *
- * Purpose:
- *
- * init heap - create first segment
- */
- HANDLE APIENTRY
- gmem_init(void)
- {
- HANDLE hNew;
- SEGHDRP hp;
- /* retry all memory allocations after calling gmem_panic */
- do {
- hNew = GlobalAlloc(GHND, ALLOCSIZE);
- if (hNew == NULL) {
- if (gmem_panic() == IDIGNORE) {
- return(NULL);
- }
- }
- } while (hNew == NULL);
- hp = (SEGHDRP) GlobalLock(hNew);
- if (hp == NULL) {
- return(NULL);
- }
- hp->hseg = hNew;
- InitializeCriticalSection(&hp->critsec);
- hp->pnext = NULL;
- gbit_init(hp->segmap, NBLKS);
- gbit_alloc(hp->segmap, 1, TO_BLKS(sizeof(SEGHDR)));
- hp->nblocks = NBLKS - TO_BLKS(sizeof(SEGHDR));
- return(hNew);
- }
- /***************************************************************************
- * Function: gmem_get
- *
- * Purpose:
- *
- * Get memory from heap
- */
- LPSTR APIENTRY
- gmem_get(HANDLE hHeap, int len)
- {
- SEGHDRP chainp;
- HANDLE hNew;
- SEGHDRP hp;
- LPSTR chp;
- long nblks;
- long start;
- long nfound;
- /* the heap is always locked (in gmem_init)- so having got the
- * pointer, we can always safely unlock it
- */
- chainp = (SEGHDRP) GlobalLock(hHeap);
- GlobalUnlock(hHeap);
- if (len < 1) {
- return(NULL);
- }
- /*
- * too big to be worth allocing from heap - get from globalalloc
- */
- if (len > MAXGALLOC) {
- /* retry all memory allocations after calling gmem_panic */
- do {
- hNew = GlobalAlloc(GHND, len);
- if (hNew == NULL) {
- if (gmem_panic() == IDIGNORE) {
- return(NULL);
- }
- }
- } while (hNew == NULL);
- chp = GlobalLock(hNew);
- if (chp == NULL) {
- return(NULL);
- }
- return(chp);
- }
- /*
- * get critical section during all access to the heap itself
- */
- EnterCriticalSection(&chainp->critsec);
- nblks = TO_BLKS(len + sizeof(HANDLE));
- for (hp = chainp; hp !=NULL; hp = hp->pnext) {
- if (hp->nblocks >= nblks) {
- nfound = gbit_findfree(hp->segmap, nblks,NBLKS, &start);
- if (nfound >= nblks) {
- gbit_alloc(hp->segmap, start, nblks);
- hp->nblocks -= nblks;
- /* convert blocknr to pointer
- * store seg handle in block
- */
- chp = (LPSTR) hp;
- chp = &chp[ (start-1) * BLKSIZE];
- * ( (HANDLE FAR *) chp) = hp->hseg;
- chp += sizeof(HANDLE);
- break;
- }
- }
- }
- if (hp == NULL) {
- /* retry all memory allocations after calling gmem_panic */
- do {
- hNew = GlobalAlloc(GHND, ALLOCSIZE);
- if (hNew == NULL) {
- if (gmem_panic() == IDIGNORE) {
- LeaveCriticalSection(&chainp->critsec);
- return(NULL);
- }
- }
- } while (hNew == NULL);
- hp = (SEGHDRP) GlobalLock(hNew);
- if (hp == NULL) {
- LeaveCriticalSection(&chainp->critsec);
- return(NULL);
- }
- hp->pnext = chainp->pnext;
- hp->hseg = hNew;
- chainp->pnext = hp;
- gbit_init(hp->segmap, NBLKS);
- gbit_alloc(hp->segmap, 1, TO_BLKS(sizeof(SEGHDR)));
- hp->nblocks = NBLKS - TO_BLKS(sizeof(SEGHDR));
- nfound = gbit_findfree(hp->segmap, nblks, NBLKS, &start);
- if (nfound >= nblks) {
- gbit_alloc(hp->segmap, start, nblks);
- hp->nblocks -= nblks;
- /* convert block nr to pointer */
- chp = (LPSTR) hp;
- chp = &chp[ (start-1) * BLKSIZE];
- /* add a handle into the block and skip past */
- * ( (HANDLE FAR *) chp) = hp->hseg;
- chp += sizeof(HANDLE);
- }
- }
- LeaveCriticalSection(&chainp->critsec);
- memset(chp, 0, len);
- return(chp);
- }
- /***************************************************************************
- * Function: gmem_free
- *
- * Purpose:
- *
- * Free memory alloced
- */
- void APIENTRY
- gmem_free(HANDLE hHeap, LPSTR ptr, int len)
- {
- SEGHDRP chainp;
- SEGHDRP hp;
- HANDLE hmem;
- long nblks, blknr;
- LPSTR chp;
- if (len < 1) {
- return;
- }
- /*
- * allocs greater than MAXGALLOC are too big to be worth
- * allocing from the heap - they will have been allocated
- * directly from globalalloc
- */
- if (len > MAXGALLOC) {
- hmem = GlobalHandle( (LPSTR) ptr);
- GlobalUnlock(hmem);
- GlobalFree(hmem);
- return;
- }
- chainp = (SEGHDRP) GlobalLock(hHeap);
- EnterCriticalSection(&chainp->critsec);
- /* just before the ptr we gave the user, is the handle to
- * the block
- */
- chp = (LPSTR) ptr;
- chp -= sizeof(HANDLE);
- hmem = * ((HANDLE FAR *) chp);
- hp = (SEGHDRP) GlobalLock(hmem);
- nblks = TO_BLKS(len + sizeof(HANDLE));
- /* convert ptr to block nr */
- blknr = TO_BLKS( (unsigned) (chp - (LPSTR) hp) ) + 1;
- gbit_free(hp->segmap, blknr, nblks);
- hp->nblocks += nblks;
- GlobalUnlock(hmem);
- LeaveCriticalSection(&chainp->critsec);
- GlobalUnlock(hHeap);
- }
- /***************************************************************************
- * Function: gmem_freeall
- *
- * Purpose:
- *
- * Free heap
- */
- void APIENTRY
- gmem_freeall(HANDLE hHeap)
- {
- SEGHDRP chainp;
- HANDLE hSeg;
- chainp = (SEGHDRP) GlobalLock(hHeap);
- /* this segment is always locked - so we need to unlock
- * it here as well as below
- */
- GlobalUnlock(hHeap);
- /* finished with the critical section -
- * caller must ensure that at this point there is no
- * longer any contention
- */
- DeleteCriticalSection(&chainp->critsec);
- while (chainp != NULL) {
- hSeg = chainp->hseg;
- chainp = chainp->pnext;
- GlobalUnlock(hSeg);
- GlobalFree(hSeg);
- }
- }
- /***************************************************************************
- * Function: gmem_panic
- *
- * Purpose:
- *
- * A memory allocation attempt has failed. Return IDIGNORE to ignore the
- * error and return NULL to the caller, and IDRETRY to retry the allocation
- * attempt.
- */
- int
- gmem_panic(void)
- {
- int code;
- extern HANDLE hLibInst;
- TCHAR szBuf1[512];
- TCHAR szBuf2[512];
- LoadString(hLibInst, IDS_MEMORY_ALLOC_FAIL, szBuf1, sizeof(szBuf1));
- LoadString(hLibInst, IDS_OUT_OF_MEMORY, szBuf2, sizeof(szBuf2));
- code = MessageBox(NULL, szBuf1, szBuf2,
- MB_ICONSTOP|MB_ABORTRETRYIGNORE);
- if (code == IDABORT) {
- /* abort this whole process */
- ExitProcess(1);
- } else {
- return(code);
- }
- }