home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) Stephen Chung, 1991-1992. All rights reserved. */
-
- #include <windows.h>
-
- #define MAGIC 0x42022667
-
- typedef struct MemoryStruct {
- long int magic;
- void far *page;
- unsigned int size;
- BOOL allocated;
- struct MemoryStruct far *next, far *prev;
- } MEMHEADER;
-
- typedef struct PageHeaderStruct {
- long int magic;
- HANDLE handle;
- unsigned int size;
- unsigned int used;
- unsigned int overhead;
- MEMHEADER far *data, far *empty;
- struct PageHeaderStruct far *next, far *prev;
- } MEMPAGEHEADER;
-
- typedef struct {
- MEMPAGEHEADER far *pages;
- int nr_pages;
- } MAINMEMHEADER;
-
- #define PAGESIZE (4 * 1024)
- #define USEABLESIZE (PAGESIZE - sizeof(MEMPAGEHEADER) - sizeof(MEMHEADER))
-
-
- static MAINMEMHEADER header = { NULL, 0 };
-
-
-
- static MEMPAGEHEADER far *AddPage(unsigned int n)
- {
- void far *cp;
- MEMHEADER far *mp;
- MEMPAGEHEADER far *p;
- HANDLE handle = NULL;
-
- handle = GlobalAlloc(GHND, n);
- if (handle == NULL) {
- ErrorMessage("Out of memory: allocating %d bytes", n);
- return (NULL);
- }
-
- if (header.pages == NULL || header.nr_pages <= 0) {
- p = header.pages = (MEMPAGEHEADER far *) GlobalLock(handle);
- p->prev = NULL;
- } else {
- for (p = header.pages; p->next != NULL; p = p->next);
- p->next = (MEMPAGEHEADER far *) GlobalLock(handle);
- p->next->prev = p;
- p = p->next;
- }
-
- p->magic = MAGIC;
- p->handle = handle;
- p->next = NULL;
- p->size = n;
- p->used = 0;
- p->overhead = sizeof(MEMPAGEHEADER) + sizeof(MEMHEADER);
-
- cp = ((char far *) p) + sizeof(MEMPAGEHEADER);
- mp = (MEMHEADER far *) cp;
-
- p->data = p->empty = mp;
-
- mp->magic = 0L;
- mp->allocated = FALSE;
- mp->page = p;
- mp->size = p->size - p->overhead;
- mp->next = mp->prev = NULL;
-
- header.nr_pages++;
-
- return (p);
- }
-
-
-
- static void DeletePage (MEMPAGEHEADER far *p)
- {
- if (p->next == NULL && p->prev == NULL) {
- header.pages = NULL;
- header.nr_pages = 0;
- GlobalFree(GlobalUnlock(p->handle));
- } else {
- if (p == header.pages) header.pages = p->next;
- header.nr_pages--;
-
- if (p->prev != NULL) p->prev->next = p->next;
- if (p->next != NULL) p->next->prev = p->prev;
-
- GlobalFree(GlobalUnlock(p->handle));
- }
- }
-
-
-
- void far *SegHeapAlloc (unsigned int n)
- {
- MEMPAGEHEADER far *p;
- MEMHEADER far *mp;
- char far *cp;
-
- if (n >= 65535) {
- ErrorMessage("MyGlobalAlloc: size (%u) > 64K!", n);
- return (NULL);
- }
-
- /* Larger than page size? */
-
- if (n > USEABLESIZE) {
- p = AddPage(n + sizeof(MEMPAGEHEADER) + sizeof(MEMHEADER));
-
- mp = p->data;
- mp->magic = MAGIC;
- mp->allocated = TRUE;
-
- p->used = n;
- p->empty = NULL;
-
- cp = ((char far *) mp) + sizeof(MEMHEADER);
- return ((void far *) cp);
- }
-
-
- /* Search for the hole */
-
- for (p = header.pages; p != NULL; p = p->next) {
- /* Scan the chains */
- if (p->size - p->used - p->overhead <= 0) continue;
- if (p->empty == NULL) continue;
-
- for (mp = p->empty; mp != NULL; mp = mp->next) {
- if (!mp->allocated && mp->size >= n) break;
- }
-
- if (mp != NULL) break;
- }
-
- /* New page needed? */
-
- if (p == NULL) {
- p = AddPage(PAGESIZE);
- mp = p->data;
- }
-
- /* Do we need to break it up? */
-
- if (mp->size - n > sizeof(MEMHEADER)) {
- MEMHEADER far *mp2;
-
- cp = ((char far *) mp) + n + sizeof(MEMHEADER);
- mp2 = (MEMHEADER far *) cp;
-
- mp2->magic = 0L;
- mp2->allocated = FALSE;
- mp2->page = p;
- mp2->size = mp->size - n - sizeof(MEMHEADER);
-
- mp2->next = mp->next;
- mp2->prev = mp;
- if (mp->next != NULL) mp->next->prev = mp2;
- mp->next = mp2;
-
-
- p->overhead += sizeof(MEMHEADER);
-
- mp->size = n;
- }
-
- mp->magic = MAGIC;
- mp->allocated = TRUE;
-
- p->used += n;
- cp = ((char far *) mp) + sizeof(MEMHEADER);
-
- /* Search for the next empty hole */
-
- for (; mp != NULL; mp = mp->next) {
- if (!mp->allocated && mp->size > 0) break;
- }
-
- p->empty = mp;
-
- return ((void far *) cp);
- }
-
-
- void SegHeapFree (void far *vp)
- {
- MEMPAGEHEADER far *p;
- MEMHEADER far *mp, far *mp2;
- char far *cp;
-
- cp = ((char far *) vp) - sizeof(MEMHEADER);
- mp = (MEMHEADER far *) cp;
-
- if (mp->magic != MAGIC || !mp->allocated) {
- ErrorMessage("Trying to deallocate invalid memory block [%Fp, %u byte%s]!\n",
- vp, mp->size, (mp->size > 1) ? "s" : "");
- return;
- }
-
- p = (MEMPAGEHEADER far *) mp->page;
- p->used -= mp->size;
-
- mp->magic = 0L;
- mp->allocated = FALSE;
-
- /* Merge? */
-
- mp2 = mp->prev;
-
- if (mp2 != NULL && !mp2->allocated) {
- mp2->next = mp->next;
- if (mp->next != NULL) mp->next->prev = mp2;
- mp2->size += mp->size + sizeof(MEMHEADER);
-
- p->overhead -= sizeof(MEMHEADER);
-
- mp = mp2;
- }
-
- mp2 = mp->next;
-
- if (mp2 != NULL && !mp2->allocated) {
- mp->next = mp2->next;
- if (mp2->next != NULL) mp2->next->prev = mp;
-
- mp->size += mp2->size + sizeof(MEMHEADER);
-
- p->overhead -= sizeof(MEMHEADER);
- }
-
- if (mp->prev == NULL && mp->next == NULL) {
- DeletePage(p);
- } else {
- if (p->empty == NULL || mp < p->empty) p->empty = mp;
- }
- }
-
-
-
- void far *SegHeapRealloc (void far *p, unsigned int n)
- {
- MEMHEADER far *mp;
- char far *cp;
-
- /* Block already large enough? */
-
- cp = ((char far *) p) - sizeof(MEMHEADER);
- mp = (MEMHEADER far *) cp;
-
- if (mp->magic != MAGIC) {
- ErrorMessage("Trying to reallocate invalid memory block [%Fp, %u byte%s]!\n",
- p, mp->size, (mp->size > 1) ? "s" : "");
- return (p);
- }
-
- if (mp->size >= n) return (p); /* No need to do anything */
-
- /* Else swap to another block */
-
- cp = SegHeapAlloc(n);
- _fmemcpy(cp, p, (mp->size >= n) ? n : mp->size);
- SegHeapFree(p);
-
- /* This is not really safe
- SegHeapFree(p);
- cp = SegHeapAlloc(n);
- if ((void far *) cp != p) {
- _fmemcpy(cp, p, (mp->size >= n) ? n : mp->size);
- }
- */
-
- return ((void far *) cp);
- }
-
-
-
- unsigned int SegHeapGetSize (void far *p)
- {
- MEMHEADER far *mp;
- char far *cp;
-
- cp = ((char far *) p) - sizeof(MEMHEADER);
-
- mp = (MEMHEADER far *) cp;
-
- if (mp->magic != MAGIC) {
- ErrorMessage("Trying to get size of invalid memory block [%Fp, %u byte%s]!\n",
- p, mp->size, (mp->size > 1) ? "s" : "");
- return (0);
- }
-
- return (mp->size);
- }
-
-
-
- void far *SegHeapDuplicate (void far *p)
- {
- unsigned int len;
- void far *p1;
-
- len = SegHeapGetSize(p);
- p1 = SegHeapAlloc(len);
- _fmemcpy(p1, p, len);
-
- return (p1);
- }
-
-
-
- void MemoryStatistics (long int *allocated, long int *used, long int *overhead)
- {
- MEMPAGEHEADER far *p;
-
- *allocated = *used = *overhead = 0L;
-
- for (p = header.pages; p != NULL; p = p->next) {
- *allocated += p->size;
- *used += p->used;
- *overhead += p->overhead;
- }
- }
-
-
- void FreeAllMemory (void)
- {
- MEMPAGEHEADER far *p, far *p1;
-
- for (p = header.pages; p != NULL; ) {
- p1 = p->next;
- GlobalFree(GlobalUnlock(p->handle));
- p = p1;
- }
-
- header.pages = NULL;
- header.nr_pages = 0;
- }
-
-
- #ifdef DEBUG
-
- /* For debugging purposes... not very pretty */
-
- void PrintMemoryChains(void)
- {
- MEMPAGEHEADER far *p;
- MEMHEADER far *mp;
- char far *cp;
- char buffer[100];
-
- /* Block already large enough? */
-
-
- for (p = header.pages; p != NULL; p = p->next) {
- for (mp = p->data; mp != NULL; mp = mp->next) {
- sprintf(buffer, "%Fp | %u | %s", mp, mp->size, mp->allocated ? "Alloc" : "Free");
- MessageBox (NULL, buffer, "Memory Chain", MB_ICONEXCLAMATION | MB_OK);
- }
- }
- }
-
- #endif DEBUG
-