home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_02_11 / 2n11008a < prev    next >
Text File  |  1991-09-10  |  9KB  |  413 lines

  1. /***************************************************/
  2. /*      Module   : MEMORY.CPP                      */
  3. /*                                                 */
  4. /*      Author   : Ismail Zia                      */
  5. /*                                                 */
  6. /*      Date     : 21-Mar-1991                     */
  7. /*                                                 */
  8. /*      Purpose  : Implementation routines of      */
  9. /*                 classes defined in memory.hpp   */
  10. /*                                                 */
  11. /*      Notes    : To be compiled with Zortech c++ */
  12. /*                 ver 2.1 in large model. for MS  */
  13. /*                 Windows 3.0, define MSW.        */
  14. /*                 Linker must link new and delete */
  15. /*                 from this object file, and not  */
  16. /*                 from standard library.          */
  17. /*                                                 */
  18. /***************************************************/
  19.  
  20. #include        "memory.hpp"
  21. #include        <stdio.h>
  22. #include        <string.h>
  23.  
  24. static MEMHEADER        DefaultSize;
  25.  
  26.  
  27.  
  28.  
  29. /* all three classes, namely MemBlock, ListItem,
  30.    and List have operators new and delete
  31.    over loaded  */
  32.  
  33. void *MemBlock::operator new(size_t sz)
  34. {
  35.     #ifdef MSW
  36.     return (void near *) LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, sz);
  37.     #else
  38.     return (void *)malloc(sz);
  39.     #endif
  40. }
  41.  
  42. void MemBlock::operator delete(void *p)
  43. {
  44.     if (p != NULL)
  45.         {
  46.             #ifdef MSW
  47.             LocalFree( (HANDLE) p);
  48.             #else
  49.             free(p);
  50.             #endif
  51.         }
  52. }
  53.  
  54.  
  55.  
  56.  
  57. /* the constructor allocates memory for member item Mem,
  58.    of the size passed to it or DefaultSize whichever is
  59.    greater, and initializes other variables. OffSet is
  60.    the offset of first free client sub-block in Mem,
  61.    Used is amount returned from Mem any time, and Size
  62.    is size in bytes of allocated to Mem     */
  63.  
  64. MemBlock::MemBlock(const MEMHEADER sz)
  65. {
  66.     MEMHEADER sz1 = DefaultSize;
  67.  
  68.     if (sz > DefaultSize)
  69.         sz1 = sz;
  70.  
  71.     #ifdef MSW
  72.     hMemHandle = GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,Size = sz1);
  73.     Mem = (MEMHEADER *)GlobalLock(hMemHandle);
  74.     #else
  75.     Mem = (MEMHEADER *)malloc(Size=sz1);
  76.     #endif
  77.  
  78.     if (Mem != NULL)
  79.             {
  80.                 #ifndef MSW
  81.                 memset(Mem,0,Size);
  82.                 #endif
  83.  
  84.                 *(MEMHEADER *)Mem = (Size-MEM_HEADER_SIZE);
  85.  
  86.                 OffSet = MEM_HEADER_SIZE;
  87.                 Used = 0;
  88.             }
  89. }
  90.  
  91.  
  92.  
  93.  
  94. /* destructor frees up memory allocated variable Mem */
  95.  
  96. MemBlock::~MemBlock(void)
  97. {
  98.     #ifdef MSW
  99.     GlobalUnlock(hMemHandle);
  100.     GlobalFree(hMemHandle);
  101.     #else
  102.     free(Mem);
  103.     #endif
  104. }
  105.  
  106.  
  107.  
  108.  
  109. /* having decided a sub-block of sufficient size is
  110.    available, this routine either breaks up this free
  111.    sub-block into two blocks first of which is returned,
  112.    or returns little more memory or equal, in any case,
  113.    it updates free list. p is pointer to available
  114.    sub-block, Last is pointer to contents of offset
  115.    of last free sub-block, sz is required size   */
  116.  
  117. void *const MemBlock::NCPointer(MEMHEADER *const p,
  118.         MEMHEADER *const Last, const MEMHEADER sz)
  119. {
  120.     MEMHEADER reminder = (*p)-sz;
  121.  
  122.     MEMHEADER *r = (MEMHEADER *)((long)p+MEM_HEADER_SIZE);
  123.  
  124.     if (reminder >= (2*MEM_HEADER_SIZE))
  125.         {
  126.             (*p) = sz;
  127.             MEMHEADER *q = (MEMHEADER *)((long)r+sz);
  128.             *q = (reminder - MEM_HEADER_SIZE);
  129.  
  130.             *Last = (MEMHEADER)((long)q+MEM_HEADER_SIZE-(long)Mem);
  131.  
  132.             *(MEMHEADER *)((long)q+MEM_HEADER_SIZE) = *r;
  133.         }
  134.     else
  135.         {
  136.             *Last = *r;
  137.         }
  138.  
  139.     Used += ((*p) + MEM_HEADER_SIZE);
  140.  
  141.     return (void *)r;
  142. }
  143.  
  144.  
  145.  
  146.  
  147. /* MemAllocate scans free list of sub-blocks, if it finds
  148.    a free sub-block of size more or equal, then calls
  149.    NCPointer to return pointer    */
  150.  
  151. void *const MemBlock::MemAllocate(const MEMHEADER size)
  152. {
  153.     if (!OffSet)
  154.         return NULL;
  155.  
  156.     MEMHEADER Current = OffSet;
  157.     MEMHEADER *Last = &OffSet;
  158.  
  159.     MEMHEADER *p;
  160.  
  161.     MEMHEADER sz = (size+1) & MEM_FREE;
  162.  
  163.  
  164.     while (Current != 0)
  165.       {
  166.         p =  (MEMHEADER *)((long)Mem + Current - MEM_HEADER_SIZE);
  167.  
  168.         if ((*p)>=sz)
  169.           {
  170.             return NCPointer(p,Last,sz);
  171.           }
  172.         Last=(MEMHEADER *)((long)p+MEM_HEADER_SIZE);
  173.  
  174.         Current = *Last;
  175.     }
  176.  
  177.     return NULL;
  178. }
  179.  
  180.  
  181.  
  182.  
  183. /* having decided a client pointer belongs to given
  184.    MemBlock, this routine updates free list of
  185.    sub-blocks, reduces the usage by amount freed,
  186.    and returns the current usage    */
  187.  
  188. const MEMHEADER MemBlock::MemFree(void *const ClientP)
  189. {
  190.     Used -= ((*(MEMHEADER *)((long)ClientP - \
  191.                 MEM_HEADER_SIZE))+MEM_HEADER_SIZE);
  192.     *(MEMHEADER *)ClientP = OffSet;
  193.     OffSet = (MEMHEADER)((long)ClientP - (long)Mem);
  194.     return Used;
  195. }
  196.  
  197.  
  198.  
  199.  
  200. /* determines if a client pointer belongs to a
  201.    given MemBlock             */
  202.  
  203. const short MemBlock::ObjInBlock(void *const obj)
  204. {
  205.     return ((long)obj >= (long)Mem) && \
  206.                        ((long)obj < (long)Mem+Size);
  207. }
  208.  
  209. void SetDefaultSize(const MEMHEADER size)
  210. {
  211.     if (size <= MEM_HEADER_SIZE)
  212.         DefaultSize = (MEM_HEADER_SIZE)<<1;
  213.     else
  214.         DefaultSize=(size+1) & MEM_FREE;
  215. }
  216. const MEMHEADER GetDefaultSize(void)
  217. {
  218.     return DefaultSize;
  219. }
  220.  
  221.  
  222.  
  223.  
  224. void *ListItem::operator new(size_t sz)
  225. {
  226.     #ifdef MSW
  227.     return (void near *) \
  228.         LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, sz);
  229.     #else
  230.     return (void *)malloc(sz);
  231.     #endif
  232. }
  233.  
  234. void ListItem::operator delete(void *p)
  235. {
  236.     if (p != NULL)
  237.         {
  238.             #ifdef MSW
  239.             LocalFree( (HANDLE) p);
  240.             #else
  241.             free(p);
  242.             #endif
  243.         }
  244.  
  245. }
  246.  
  247.  
  248.  
  249. void *List::operator new(size_t sz)
  250. {
  251.         #ifdef MSW
  252.         return (void near *) \
  253.           LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sz);
  254.         #else
  255.         return (void *)malloc(sz);
  256.         #endif
  257. }
  258.  
  259. void List::operator delete(void *p)
  260. {
  261.     if (p != NULL)
  262.         {
  263.             #ifdef MSW
  264.             LocalFree( (HANDLE) p);
  265.             #else
  266.             free(p);
  267.             #endif
  268.         }
  269. }
  270.  
  271. List::List(void)
  272. {
  273.     ListItem *tmp= new ListItem(DefaultSize);
  274.     Tail = Head = tmp;
  275. }
  276.  
  277.  
  278.  
  279. /* just to make sure, removes all ListItems from
  280.    List. In normal termination, all ListItems must
  281.    have been freed automatically, except the Head */
  282.  
  283. List::~List(void)
  284. {
  285.     ListItem *tmp = Head;
  286.  
  287.     while (tmp != NULL)
  288.         {
  289.             Head = tmp->GetNext();
  290.             delete tmp;
  291.             tmp = (ListItem *)Head;
  292.         }
  293. }
  294.  
  295.  
  296.  
  297. /* Searches all ListItems, starting with Head, for
  298.    MemBlock having sufficient free, if not found
  299.    then appends a new ListItem to the List   */
  300.  
  301. void *const List::MemAlloc(const MEMHEADER sz)
  302. {
  303.     ListItem *Li = Head;
  304.  
  305.     while (Li != NULL)
  306.         {
  307.             void *p = Li->MemAlloc(sz);
  308.             if (p != NULL)
  309.                 return p;
  310.  
  311.              Li = Li->GetNext();
  312.         }
  313.  
  314.     Li = new ListItem(sz+MEM_HEADER_SIZE);
  315.  
  316.     ListItem *tmp = Tail;
  317.     tmp->SetNext(Li);
  318.     Tail = Li;
  319.  
  320.     return Li->MemAlloc(sz);
  321. }
  322.  
  323.  
  324.  
  325. /* Searches all ListItems, starting with Head, for
  326.    the MemBlock to which pointer to be freed belongs,
  327.    after freeing, if the usage returned is = 0, then
  328.    frees up that ListItem and updates chain    */
  329.  
  330. void List::MemFree(void *const obj)
  331. {
  332.     ListItem *Li = Head;
  333.     ListItem *Lst = NULL;
  334.  
  335.     while (Li != NULL)
  336.       {
  337.         if (Li->ObjInBlock(obj))
  338.           {
  339.             if ( ! Li->MemFree(obj))
  340.               {
  341.                 if (Lst != NULL)
  342.                   {
  343.                     Lst->SetNext(Li->GetNext());
  344.  
  345.                     if (Tail == Li)
  346.                       Tail = Lst;
  347.  
  348.                     delete Li;
  349.                   }
  350.               }
  351.             return;
  352.           }
  353.         Lst = Li;
  354.         Li=Li->GetNext();
  355.       }
  356. }
  357.  
  358.  
  359.  
  360. List   *GMemList;
  361.  
  362. void InitMem(const MEMHEADER sz)
  363. {
  364.     SetDefaultSize(sz);
  365.     GMemList = new List;
  366. }
  367.  
  368. void EndMem(void)
  369. {
  370.     delete GMemList;
  371. }
  372.  
  373. #ifndef MSW
  374. void MemErr(void)
  375. {
  376.     printf("Memory Allocation Failed\n");
  377. }
  378.  
  379. #else
  380.  
  381. void MemErr(void) 
  382. {
  383.     MessageBox(NULL, "Memory Allocation  Failed",
  384.                NULL, MB_ICONEXCLAMATION | MB_OK);
  385. }
  386.  
  387. #endif
  388.  
  389. /* Global new and delete operators overloaded  */
  390.   
  391. void *operator new(size_t size)
  392. {   
  393.     void *p;
  394.  
  395.     if (size<2)
  396.         size=2;
  397.  
  398.     p = GMemList->MemAlloc(size);
  399.  
  400.     if (p == NULL)
  401.         MemErr();
  402.  
  403.     return p;
  404. }
  405.  
  406. void operator delete(void *obj)
  407. {
  408.     if (obj != NULL)
  409.         GMemList->MemFree(obj);
  410. }
  411.  
  412.         
  413.