home *** CD-ROM | disk | FTP | other *** search
- /*
- #### # # # #
- # # # # # The FreeWare C library for
- # # ## ### # # # # ### RISC OS machines
- # # # # # # # # # # # ___________________________________
- # # #### ### ## # # # #
- # # # # # # # # # # Please refer to the accompanying
- #### ### #### # # ##### # ### documentation for conditions of use
- ________________________________________________________________________
-
- File: Mem.Compact.c
- Author: Copyright © 1993 Jason Williams
- Version: 1.00 (12 May 1993)
- Purpose: Dynamic memory manager - heap compaction
- */
-
- #include "MemDefs.h"
-
- #include <string.h>
-
-
- static void Mem__ShiftHeap(mem_header *first, mem_header *last, int by)
- /* Shifts all chunks between 'first' and 'last' (INCLUSIVE) up or down
- * by 'by' bytes, fixing all anchors as it goes, and returning with a
- * new (& valid) heap. (Assuming that the portions not being moved are
- * all valid!)
- *
- * Currently, 'by' MUST be negative.
- */
- {
- mem_header *chunk;
- int tempstore;
-
- /* Fix all the anchors to point at the new positions of these chunks
- */
- chunk = first;
- while ((int) chunk <= (int) last)
- {
- if (chunk->datasize > 0)
- *(chunk->handle) = (void *) (((int) (*chunk->handle)) + by);
- chunk = Mem__NextChunk(chunk);
- }
-
- /* Move all these chunks by 'by' bytes.
- * 'chunk' is now set to point at the start of the chunk after 'last'.
- * (Note that this may point at a non-existant chunk past the end of the
- * heap)
- */
- chunk = (mem_header *) ( ((int) last) + last->realsize );
- memmove((char *) first + by, (char *) first, ((int) chunk) - ((int) first));
-
- /* Now we must make a new free chunk with the space we have created
- * (before or) after the data we have moved. The simplest way to do this
- * is to add the space onto the end of preceeding chunk, and then call
- * Mem__SplitOffFreeChunk() to resolve everything for us.
- */
- if (by < 0)
- {
- last->realsize += by;
- if (last != mem__lastchunk)
- {
- chunk = Mem__NextChunk(last);
- chunk->prevrealsize = last->realsize;
- }
- tempstore = mem_autocompact;
- mem_autocompact = mem_NOCOMPACT; /* Don't call us recursively! */
- Mem__SplitOffFreeChunk(last);
- mem_autocompact = tempstore;
- }
- /* else
- * Error_ReportFatalInternal("Mem__ShiftHeap failure");
- */
- }
-
-
- extern void Mem_Compact(void)
- /* Compacts the heap, moving all freespace to the end of the heap, and then
- * releases as much of this freespace as possible back into the WIMP freepool.
- *
- * Note that the current implementation, although short and easy to write,
- * is extremely inefficient. This shouldn't make much of a difference though
- * unless you alloc and dealloc a LOT of medium-sized chunks between calls
- * to Mem_Compact.
- */
- {
- mem_header *chunk, *freechunk, *lastdatachunk;
-
- if (mem__iscompact) return; /* Don't compact if not necessary */
-
- freechunk = (mem_header *) mem__heap;
- while (TRUE)
- {
- while (!ISFREE(freechunk) && freechunk != mem__lastchunk)
- freechunk = Mem__NextChunk(freechunk);
-
- if (freechunk == mem__lastchunk) break; /* No 'trapped' free chunks */
-
- /* Have found a free chunk. Shift chunks above it down in memory,
- * adjusting their anchors as necessary.
- * For greater efficiency, rather than shifting the rest of the heap,
- * we search for the end of this run of in-use chunks, and just shift
- * them down, enlarging the free chunk at the end of them.
- */
- chunk = Mem__NextChunk(freechunk);
- lastdatachunk = chunk;
- while (!ISFREE(lastdatachunk) && lastdatachunk != mem__lastchunk)
- lastdatachunk = Mem__NextChunk(lastdatachunk);
-
- if (ISFREE(lastdatachunk))
- lastdatachunk = Mem__PrevChunk(lastdatachunk);
-
- Mem__ShiftHeap(chunk, lastdatachunk, -freechunk->realsize);
-
- /* And back around for another go - chunk has been moved down into
- * the same place as 'freechunk', so we just continue from there...
- */
- }
-
- /* Finally, adjust the WimpSlot to the minimum that we require, and adjust
- * the last (free) chunk as appropriate
- */
-
- Mem__ReduceSlot();
- mem__iscompact = TRUE;
- }
-