home *** CD-ROM | disk | FTP | other *** search
/ RISC DISC 1 / RISC_DISC_1.iso / pd_share / code / desklib / Libraries / Mem / c / Compact < prev    next >
Encoding:
Text File  |  1994-05-22  |  4.5 KB  |  132 lines

  1. /*
  2.     ####             #    #     # #
  3.     #   #            #    #       #          The FreeWare C library for 
  4.     #   #  ##   ###  #  # #     # ###             RISC OS machines
  5.     #   # #  # #     # #  #     # #  #   ___________________________________
  6.     #   # ####  ###  ##   #     # #  #                                      
  7.     #   # #        # # #  #     # #  #    Please refer to the accompanying
  8.     ####   ### ####  #  # ##### # ###    documentation for conditions of use
  9.     ________________________________________________________________________
  10.  
  11.     File:    Mem.Compact.c
  12.     Author:  Copyright © 1993, 1994 Jason Williams and Jason Howat
  13.     Version: 1.01 (12 May 1994)
  14.     Purpose: Dynamic memory manager - heap compaction
  15. */
  16.  
  17. #include "MemDefs.h"
  18.  
  19. #include <string.h>
  20.  
  21.  
  22. static void Mem__ShiftHeap(mem_header *first, mem_header *last, int by)
  23. /*  Shifts all chunks between 'first' and 'last' (INCLUSIVE) up or down
  24.  *  by 'by' bytes, fixing all anchors as it goes, and returning with a
  25.  *  new (& valid) heap. (Assuming that the portions not being moved are
  26.  *  all valid!)
  27.  *
  28.  *  Currently, 'by' MUST be negative.
  29.  */
  30. {
  31.   mem_header *chunk,
  32.              *old;
  33.   int        tempstore;
  34.  
  35.   /*  Fix all the anchors to point at the new positions of these chunks
  36.    */
  37.   chunk = first;
  38.   while ((int) chunk <= (int) last)
  39.   {
  40.     if (chunk->datasize > 0)
  41.       *(chunk->handle) = (void *) (((int) (*chunk->handle)) + by);
  42.     chunk = Mem__NextChunk(chunk);
  43.   }
  44.  
  45.   /*  Move all these chunks by 'by' bytes.
  46.    *  'chunk' is now set to point at the start of the chunk after 'last'.
  47.    *  (Note that this may point at a non-existant chunk past the end of the
  48.    *  heap)
  49.    */
  50.   chunk = (mem_header *) ( ((int) last) + last->realsize );
  51.  
  52.   /*  Now we must make a new free chunk with the space we have created
  53.    *  (before or) after the data we have moved. The simplest way to do this
  54.    *  is to add the space onto the end of preceeding chunk, and then call
  55.    *  Mem__SplitOffFreeChunk() to resolve everything for us.
  56.    */
  57.   if (by < 0)
  58.   {
  59.     old = (mem_header *) ((int)first + by);   /*** JDH added ***/
  60.     first->prevrealsize = old->prevrealsize;  /*** JDH added ***/
  61.  
  62.     last->realsize -= by;  /*** JDH changed from += ***/
  63.     if (last != mem__lastchunk)
  64.     {
  65.       chunk = Mem__NextChunk(last);
  66.       chunk->prevrealsize = last->realsize;
  67.     }
  68.                                 /*** JDH moved ***/
  69.     memmove((char *) first + by, (char *) first, ((int) chunk) - ((int) first));
  70.  
  71.     tempstore = mem_autocompact;
  72.     mem_autocompact = mem_NOCOMPACT;           /* Don't call us recursively! */
  73.     Mem__SplitOffFreeChunk((mem_header *)((int)last + by)); /*** JDH changed ***/  
  74.     mem_autocompact = tempstore;
  75.   }
  76. /*  else
  77.  *    Error_ReportFatalInternal("Mem__ShiftHeap failure");
  78.  */
  79. }
  80.  
  81.  
  82. extern void Mem_Compact(void)
  83. /*  Compacts the heap, moving all freespace to the end of the heap, and then
  84.  *  releases as much of this freespace as possible back into the WIMP freepool.
  85.  *
  86.  *  Note that the current implementation, although short and easy to write,
  87.  *  is extremely inefficient. This shouldn't make much of a difference though
  88.  *  unless you alloc and dealloc a LOT of medium-sized chunks between calls
  89.  *  to Mem_Compact.
  90.  */
  91. {
  92.   mem_header *chunk, *freechunk, *lastdatachunk;
  93.  
  94.   if (mem__iscompact) return;              /* Don't compact if not necessary */
  95.  
  96.   freechunk = (mem_header *) mem__heap;
  97.   while (TRUE)
  98.   {
  99.     while (!ISFREE(freechunk) && freechunk != mem__lastchunk)
  100.       freechunk = Mem__NextChunk(freechunk);
  101.  
  102.     if (freechunk == mem__lastchunk) break;      /* No 'trapped' free chunks */
  103.  
  104.     /*  Have found a free chunk. Shift chunks above it down in memory,
  105.      *  adjusting their anchors as necessary.
  106.      *  For greater efficiency, rather than shifting the rest of the heap,
  107.      *  we search for the end of this run of in-use chunks, and just shift
  108.      *  them down, enlarging the free chunk at the end of them.
  109.      */
  110.     chunk = Mem__NextChunk(freechunk);
  111.     lastdatachunk = chunk;
  112.     while (!ISFREE(lastdatachunk) && lastdatachunk != mem__lastchunk)
  113.       lastdatachunk = Mem__NextChunk(lastdatachunk);
  114.  
  115.     if (ISFREE(lastdatachunk))
  116.       lastdatachunk = Mem__PrevChunk(lastdatachunk);
  117.  
  118.     Mem__ShiftHeap(chunk, lastdatachunk, -freechunk->realsize);
  119.  
  120.     /*  And back around for another go - chunk has been moved down into
  121.      *  the same place as 'freechunk', so we just continue from there...
  122.      */
  123.   }
  124.  
  125.   /* Finally, adjust the WimpSlot to the minimum that we require, and adjust
  126.    * the last (free) chunk as appropriate
  127.    */
  128.  
  129.   Mem__ReduceSlot();
  130.   mem__iscompact = TRUE;
  131. }
  132.