home *** CD-ROM | disk | FTP | other *** search
/ Languages Around the World / LanguageWorld.iso / language / japanese / win_prog / win_jwp / memory.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-31  |  10.6 KB  |  481 lines

  1. /* Copyright (C) Stephen Chung, 1991-1993.  All rights reserved. */
  2.  
  3. #include "jwp.h"
  4.  
  5. #define MAGIC           0x42022667L
  6.  
  7. typedef struct MemoryStruct {
  8.     long int magic;
  9.     void far *page;
  10.     unsigned int size;
  11.     BOOL allocated;
  12.     struct MemoryStruct far *next, far *prev;
  13. } MEMHEADER;
  14.  
  15. typedef struct PageHeaderStruct {
  16.     long int magic;
  17.     HANDLE handle;
  18.     unsigned int size;
  19.     unsigned int used;
  20.     unsigned int overhead;
  21.     MEMHEADER far *data, far *empty;
  22.     struct PageHeaderStruct far *next, far *prev;
  23. } MEMPAGEHEADER;
  24.  
  25. typedef struct {
  26.     MEMPAGEHEADER far *pages;
  27.     int nr_pages;
  28. } MAINMEMHEADER;
  29.  
  30. #define PAGESIZE        (4 * 1024)
  31. #define USEABLESIZE     (PAGESIZE - sizeof(MEMPAGEHEADER) - sizeof(MEMHEADER))
  32.  
  33.  
  34. static MAINMEMHEADER header = { NULL, 0 };
  35. static BOOL NoErrors = FALSE;
  36.  
  37.  
  38.  
  39. void EnableNullPointers (BOOL enable)
  40. {
  41.     NoErrors = enable;
  42. }
  43.  
  44.  
  45. /* Make room by trimming off undo's */
  46.  
  47. static BOOL MakeRoom (void)
  48. {
  49.     FILEOPTIONS *f, *f1;
  50.     UNDOBUF far *up;
  51.     int largest;
  52.     void far *ptr;
  53.  
  54.  
  55.     largest = -1;
  56.  
  57.     for (f = fileoptions; f != NULL; f = f->next) {
  58.         if (f->undo != NULL && f->undolevels > largest) {
  59.             largest = f->undolevels;
  60.             f1 = f;
  61.         }
  62.     }
  63.  
  64.     if (largest < 0) return (FALSE);
  65.  
  66.  
  67.     /* Start trimming */
  68.  
  69.     up = f1->undotail->prev;
  70.     FreeUndo(f1->undotail);
  71.  
  72.     f1->undolevels--;
  73.     if (up != NULL) up->next = NULL;
  74.  
  75.     if (up == NULL) {
  76.         f1->undo = f1->undotail = NULL;
  77.         f1->undolevels = 0;
  78.     }
  79.  
  80.     return (TRUE);
  81. }
  82.  
  83.  
  84.  
  85. static MEMPAGEHEADER far *AddPage(unsigned int n)
  86. {
  87.     void far *cp;
  88.     MEMHEADER far *mp;
  89.     MEMPAGEHEADER far *p;
  90.     HANDLE handle = NULL;
  91.  
  92.     handle = GlobalAlloc(GHND, n);
  93.     if (handle == NULL) return (NULL);
  94.  
  95.     if (header.pages == NULL || header.nr_pages <= 0) {
  96.         p = header.pages = (MEMPAGEHEADER far *) GlobalLock(handle);
  97.         p->prev = NULL;
  98.     } else {
  99.         for (p = header.pages; p->next != NULL; p = p->next);
  100.         p->next = (MEMPAGEHEADER far *) GlobalLock(handle);
  101.         p->next->prev = p;
  102.         p = p->next;
  103.     }
  104.  
  105.     p->magic = MAGIC;
  106.     p->handle = handle;
  107.     p->next = NULL;
  108.     p->size = n;
  109.     p->used = 0;
  110.     p->overhead = sizeof(MEMPAGEHEADER) + sizeof(MEMHEADER);
  111.  
  112.     cp = ((char far *) p) + sizeof(MEMPAGEHEADER);
  113.     mp = (MEMHEADER far *) cp;
  114.  
  115.     p->data = p->empty = mp;
  116.  
  117.     mp->magic = 0L;
  118.     mp->allocated = FALSE;
  119.     mp->page = p;
  120.     mp->size = p->size - p->overhead;
  121.     mp->next = mp->prev = NULL;
  122.  
  123.     header.nr_pages++;
  124.  
  125.     return (p);
  126. }
  127.  
  128.  
  129.  
  130. static void DeletePage (MEMPAGEHEADER far *p)
  131. {
  132.     if (p->next == NULL && p->prev == NULL) {
  133.         header.pages = NULL;
  134.         header.nr_pages = 0;
  135.         if (GlobalUnlock(p->handle) || GlobalFree(p->handle) != NULL) {
  136.             ErrorMessage(global.hwnd, "Cannot free memory page 0x%x!", p->handle);
  137.         }
  138.     } else {
  139.         if (p == header.pages) header.pages = p->next;
  140.         header.nr_pages--;
  141.  
  142.         if (p->prev != NULL) p->prev->next = p->next;
  143.         if (p->next != NULL) p->next->prev = p->prev;
  144.  
  145.         if (GlobalUnlock(p->handle) || GlobalFree(p->handle) != NULL) {
  146.             ErrorMessage(global.hwnd, "Cannot free memory page 0x%x!", p->handle);
  147.         }
  148.     }
  149. }
  150.  
  151.  
  152.  
  153. void far *SegHeapAlloc (unsigned int n)
  154. {
  155.     MEMPAGEHEADER far *p = NULL;
  156.     MEMHEADER far *mp;
  157.     char far *cp;
  158.  
  159.     if (n >= 65535) {
  160.         ErrorMessage(global.hwnd, "SegHeapAlloc: size (%u) > 64K!\n\n"
  161.                                   "The program is not stable.  You should save your work NOW!",
  162.                                   n);
  163.         n = C64K;
  164.     }
  165.  
  166.     /* Larger than page size? */
  167.  
  168.     if (n > USEABLESIZE) {
  169.         for (;;) {
  170.             p = AddPage(n + sizeof(MEMPAGEHEADER) + sizeof(MEMHEADER));
  171.  
  172.             if (p != NULL) break;
  173.  
  174.             if (NoErrors) return (NULL);
  175.             if (MakeRoom()) continue;
  176.             if (!RetryMessage("Out of Global Memory:\nAllocating %u bytes", n))
  177.                 return (NULL);
  178.         }
  179.  
  180.         mp = p->data;
  181.         mp->magic = MAGIC;
  182.         mp->allocated = TRUE;
  183.  
  184.         mp->next = mp->prev = NULL;
  185.  
  186.         p->used = n;
  187.         p->empty = NULL;
  188.  
  189.         cp = ((char far *) mp) + sizeof(MEMHEADER);
  190.         _fmemset(cp, 0, n);
  191.  
  192.         return ((void far *) cp);
  193.     }
  194.  
  195.  
  196. LookForHole:
  197.  
  198.     /* Search for the hole */
  199.  
  200.     for (p = header.pages; p != NULL; p = p->next) {
  201.         /* Scan the chains */
  202.         if (p->size - p->used - p->overhead <= 0) continue;
  203.         if (p->empty == NULL) continue;
  204.  
  205.         for (mp = p->empty; mp != NULL; mp = mp->next) {
  206.             if (!mp->allocated && mp->size >= n) break;
  207.         }
  208.  
  209.         if (mp != NULL) break;
  210.     }
  211.  
  212.     /* New page needed? */
  213.  
  214.     if (p == NULL) {
  215.         for (;;) {
  216.             p = AddPage(PAGESIZE);
  217.  
  218.             if (p != NULL) break;
  219.  
  220.             if (NoErrors) return (NULL);
  221.             if (MakeRoom()) goto LookForHole;
  222.             if (!RetryMessage("Out of Global Memory:\nAllocating %u bytes", n))
  223.                 return (NULL);
  224.         }
  225.  
  226.         mp = p->data;
  227.     }
  228.  
  229.     /* Do we need to break it up? */
  230.  
  231.     if (mp->size - n > sizeof(MEMHEADER)) {
  232.         MEMHEADER far *mp2;
  233.  
  234.         cp = ((char far *) mp) + n + sizeof(MEMHEADER);
  235.         mp2 = (MEMHEADER far *) cp;
  236.  
  237.         mp2->magic = 0L;
  238.         mp2->allocated = FALSE;
  239.         mp2->page = p;
  240.         mp2->size = mp->size - n - sizeof(MEMHEADER);
  241.  
  242.         mp2->next = mp->next;
  243.         mp2->prev = mp;
  244.         if (mp->next != NULL) mp->next->prev = mp2;
  245.         mp->next = mp2;
  246.  
  247.  
  248.         p->overhead += sizeof(MEMHEADER);
  249.  
  250.         mp->size = n;
  251.     }
  252.  
  253.     mp->magic = MAGIC;
  254.     mp->allocated = TRUE;
  255.  
  256.     p->used += n;
  257.     cp = ((char far *) mp) + sizeof(MEMHEADER);
  258.  
  259.     /* Search for the next empty hole */
  260.  
  261.     for (; mp != NULL; mp = mp->next) {
  262.         if (!mp->allocated && mp->size > 0) break;
  263.     }
  264.  
  265.     p->empty = mp;
  266.  
  267.     _fmemset(cp, 0, n);
  268.  
  269.     return ((void far *) cp);
  270. }
  271.  
  272.  
  273. void SegHeapFree (void far *vp)
  274. {
  275.     MEMPAGEHEADER far *p;
  276.     MEMHEADER far *mp, far *mp2;
  277.     char far *cp;
  278.  
  279.     cp = ((char far *) vp) - sizeof(MEMHEADER);
  280.     mp = (MEMHEADER far *) cp;
  281.  
  282.     if (mp->magic != MAGIC || !mp->allocated) {
  283.         ErrorMessage(global.hwnd, "Trying to deallocate invalid memory block [%Fp, %u byte%s]!\n\n"
  284.                                   "The program is not stable.  You should save your work NOW!",
  285.                         vp, mp->size, (mp->size > 1) ? "s" : "");
  286.         return;
  287.     }
  288.  
  289.     p = (MEMPAGEHEADER far *) mp->page;
  290.     p->used -= mp->size;
  291.  
  292.     mp->magic = 0L;
  293.     mp->allocated = FALSE;
  294.  
  295.     /* Merge? */
  296.  
  297.     mp2 = mp->prev;
  298.  
  299.     if (mp2 != NULL && !mp2->allocated) {
  300.         mp2->next = mp->next;
  301.         if (mp->next != NULL) mp->next->prev = mp2;
  302.         mp2->size += mp->size + sizeof(MEMHEADER);
  303.  
  304.         p->overhead -= sizeof(MEMHEADER);
  305.  
  306.         mp = mp2;
  307.     }
  308.  
  309.     mp2 = mp->next;
  310.  
  311.     if (mp2 != NULL && !mp2->allocated) {
  312.         mp->next = mp2->next;
  313.         if (mp2->next != NULL) mp2->next->prev = mp;
  314.  
  315.         mp->size += mp2->size + sizeof(MEMHEADER);
  316.  
  317.         p->overhead -= sizeof(MEMHEADER);
  318.     }
  319.  
  320.     if (mp->prev == NULL && mp->next == NULL) {
  321.         DeletePage(p);
  322.     } else {
  323.         if (p->empty == NULL || mp < p->empty) p->empty = mp;
  324.     }
  325. }
  326.  
  327.  
  328.  
  329. void far *SegHeapRealloc (void far *p, unsigned int n)
  330. {
  331.     MEMHEADER far *mp;
  332.     char far *cp;
  333.  
  334.     /* Block already large enough? */
  335.  
  336.     cp = ((char far *) p) - sizeof(MEMHEADER);
  337.     mp = (MEMHEADER far *) cp;
  338.  
  339.     if (mp->magic != MAGIC) {
  340.         ErrorMessage(global.hwnd, "Trying to reallocate invalid memory block [%Fp, %u byte%s]!\n\n"
  341.                                   "The program is not stable.  You should save your work NOW!",
  342.                         p, mp->size, (mp->size > 1) ? "s" : "");
  343.  
  344.         /* Minimize the damage */
  345.  
  346.         cp = SegHeapAlloc(n);
  347.         if (cp == NULL) return (NULL);
  348.         _fmemcpy(cp, p, (mp->size >= n) ? n : mp->size);
  349.         return (cp);
  350.     }
  351.  
  352.     if (mp->size >= n) return (p);      /* No need to do anything */
  353.  
  354.     /* Else swap to another block */
  355.  
  356.     cp = SegHeapAlloc(n);
  357.     if (cp == NULL) return (NULL);
  358.  
  359.     _fmemcpy(cp, p, (mp->size >= n) ? n : mp->size);
  360.     SegHeapFree(p);
  361.  
  362.     /* This is not really safe
  363.     SegHeapFree(p);
  364.     cp = SegHeapAlloc(n);
  365.     if ((void far *) cp != p) {
  366.         _fmemcpy(cp, p, (mp->size >= n) ? n : mp->size);
  367.     }
  368.     */
  369.  
  370.     return ((void far *) cp);
  371. }
  372.  
  373.  
  374.  
  375. unsigned int SegHeapGetSize (void far *p)
  376. {
  377.     MEMHEADER far *mp;
  378.     char far *cp;
  379.  
  380.     cp = ((char far *) p) - sizeof(MEMHEADER);
  381.  
  382.     mp = (MEMHEADER far *) cp;
  383.  
  384.     if (mp->magic != MAGIC) {
  385.         ErrorMessage(global.hwnd, "Trying to get size of invalid memory block [%Fp, %u byte%s]!\n\n"
  386.                                   "The program is not stable.  You should save your work NOW!",
  387.                         p, mp->size, (mp->size > 1) ? "s" : "");
  388.         return (0);
  389.     }
  390.  
  391.     return (mp->size);
  392. }
  393.  
  394.  
  395.  
  396. void far *SegHeapDuplicate (void far *p)
  397. {
  398.     unsigned int len;
  399.     void far *p1;
  400.  
  401.     len = SegHeapGetSize(p);
  402.     p1 = SegHeapAlloc(len);
  403.     _fmemcpy(p1, p, len);
  404.  
  405.     return (p1);
  406. }
  407.  
  408.  
  409.  
  410. void *MyLocalAlloc (unsigned int size)
  411. {
  412.     void *p = NULL;
  413.  
  414.     while (p == NULL) {
  415.         p = (void *) LocalAlloc(LPTR, size);
  416.         if (p == NULL) {
  417.             if (NoErrors) return (NULL);
  418.  
  419.             if (!RetryMessage("Out of Local Memory:\nAllocating %u bytes", size))
  420.                 return (NULL);
  421.         }
  422.     }
  423.  
  424.     return (p);
  425. }
  426.  
  427.  
  428.  
  429. void CountMemoryUsage (long int *allocated, long int *used, long int *overhead)
  430. {
  431.     MEMPAGEHEADER far *p;
  432.  
  433.     *allocated = *used = *overhead = 0L;
  434.  
  435.     for (p = header.pages; p != NULL; p = p->next) {
  436.         *allocated += p->size;
  437.         *used += p->used;
  438.         *overhead += p->overhead;
  439.     }
  440. }
  441.  
  442.  
  443. void FreeAllMemory (void)
  444. {
  445.     MEMPAGEHEADER far *p, far *p1;
  446.  
  447.     for (p = header.pages; p != NULL; ) {
  448.         p1 = p->next;
  449.         GlobalFree(GlobalUnlock(p->handle));
  450.         p = p1;
  451.     }
  452.  
  453.     header.pages = NULL;
  454.     header.nr_pages = 0;
  455. }
  456.  
  457.  
  458. #ifdef DEBUG
  459.  
  460. /* For debugging purposes...  not very pretty */
  461.  
  462. void PrintMemoryChains(void)
  463. {
  464.     MEMPAGEHEADER far *p;
  465.     MEMHEADER far *mp;
  466.     char far *cp;
  467.     char buffer[100];
  468.  
  469.     /* Block already large enough? */
  470.  
  471.  
  472.     for (p = header.pages; p != NULL; p = p->next) {
  473.         for (mp = p->data; mp != NULL; mp = mp->next) {
  474.             sprintf(buffer, "%Fp | %u | %s", mp, mp->size, mp->allocated ? "Alloc" : "Free");
  475.             MessageBox (NULL, buffer, "Memory Chain", MB_ICONEXCLAMATION | MB_OK);
  476.         }
  477.     }
  478. }
  479.  
  480. #endif DEBUG
  481.