home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 375.lha / IncrStorageManager_v1.0 / DynItemList.mod < prev    next >
Text File  |  1990-05-02  |  7KB  |  280 lines

  1. IMPLEMENTATION MODULE DynItemList;
  2.  
  3. (* Product: Incremental Storage Manager
  4.  
  5.    Version: 1.0
  6.  
  7.    Author:
  8.         Daniel B. Hankins
  9.         143 Montgomery Street
  10.         Poughkeepsie, NY 12601
  11.         dan-hankins@cup.portal.com
  12.  
  13.    Creation Date: 1989
  14.  
  15.    Release  Date: November 21, 1989
  16.  
  17.    Notice of Intellectual Property:
  18.         This material is *NOT COPYRIGHTED*.  By this notice, I hereby place
  19.    this program and all its parts in the public domain, under the definitions
  20.    and restrictions of United States law.
  21.  
  22.    History of Revisions:
  23.         None yet.
  24. *)
  25.  
  26. FROM SYSTEM    IMPORT ADDRESS, TSIZE;
  27. FROM WordAlign IMPORT WordAlign;
  28. FROM Storage   IMPORT ALLOCATE, DEALLOCATE;
  29.  
  30. IMPORT DynItem;
  31.  
  32. TYPE
  33.   Object     = POINTER TO ListRecord;
  34.   ListRecord = RECORD
  35.                  PrevList, NextList:          Object;
  36.                  NextFreeByte:                ADDRESS;
  37.                  AmountLeft, ItemCount, Size: LONGCARD;
  38.                  FirstItem, LastItem,
  39.                  LowGapItem, CurrentGapItem:  DynItem.Object;
  40.                END;
  41.  
  42. VAR
  43.   FirstList:      Object;
  44.   ListRecordSize: LONGCARD;
  45.   NilDynItem:     DynItem.Object;
  46.  
  47. CONST
  48.   BlockSizeResolution = 1024;
  49.  
  50.  
  51. PROCEDURE GetListWithSpace(Size: LONGCARD): Object;
  52. VAR
  53.   NewList: Object;
  54. BEGIN
  55.   IF FirstList = NIL THEN
  56.     FirstList := New(Size);
  57.     RETURN FirstList;
  58.   END;
  59.  
  60.   NewList := FindListWithSpace(FirstList, Size);
  61.   IF NewList <> NIL THEN
  62.     RETURN NewList;
  63.   END;
  64.  
  65.   NewList := New(Size);
  66.   IF NewList = NIL THEN
  67.     RETURN NIL;
  68.   END;
  69.  
  70.   LinkInList(NewList, FirstList);
  71.   RETURN NewList;
  72. END GetListWithSpace;
  73.  
  74.  
  75. PROCEDURE New(Size: LONGCARD): Object;
  76. VAR
  77.   NewObject: Object;
  78. BEGIN
  79.   Size := Size + ListRecordSize;
  80.   Size := ((Size - 1) DIV BlockSizeResolution + 1) * BlockSizeResolution;
  81.   ALLOCATE(NewObject, Size);
  82.   IF NewObject = NIL THEN
  83.     RETURN NIL;
  84.   END;
  85.   NewObject^.PrevList     := NIL;
  86.   NewObject^.NextList     := NIL;
  87.   NewObject^.AmountLeft   := Size - ListRecordSize;
  88.   NewObject^.Size         := Size;
  89.   NewObject^.NextFreeByte := ADDRESS(LONGCARD(NewObject) + ListRecordSize);
  90.   NewObject^.FirstItem      := NilDynItem;
  91.   NewObject^.LastItem       := NilDynItem;
  92.   NewObject^.LowGapItem     := NilDynItem;
  93.   NewObject^.CurrentGapItem := NilDynItem;
  94.   RETURN NewObject;
  95. END New;
  96.  
  97.  
  98. PROCEDURE FindListWithSpace(List: Object; Size: LONGCARD): Object;
  99. BEGIN
  100.   LOOP
  101.     IF List = NIL THEN
  102.       RETURN NIL;
  103.     END;
  104.  
  105.     IF List^.AmountLeft >= Size THEN
  106.       RETURN List;
  107.     END;
  108.  
  109.     List := List^.NextList;
  110.   END;
  111. END FindListWithSpace;
  112.  
  113.  
  114. PROCEDURE LinkInList(NewList: Object; OldList: Object);
  115. BEGIN
  116.   IF OldList <> NIL THEN
  117.     NewList^.PrevList := OldList;
  118.     NewList^.NextList := OldList^.NextList;
  119.     NewList^.PrevList^.NextList := NewList;
  120.     IF NewList^.NextList <> NIL THEN
  121.       NewList^.NextList^.PrevList := NewList;
  122.     END;
  123.   ELSE
  124.     NewList^.PrevList := NIL;
  125.     NewList^.NextList := NIL;
  126.   END;
  127. END LinkInList;
  128.  
  129.  
  130. PROCEDURE UnlinkList(List: Object);
  131. BEGIN
  132.   IF List^.PrevList <> NIL THEN
  133.     List^.PrevList^.NextList := List^.NextList;
  134.   END;
  135.  
  136.   IF List^.NextList <> NIL THEN
  137.     List^.NextList^.PrevList := List^.PrevList;
  138.   END;
  139.  
  140.   IF List = FirstList THEN
  141.     FirstList := List^.NextList;
  142.   END;
  143. END UnlinkList;
  144.  
  145.  
  146. PROCEDURE GetChunk(List: Object; Size: LONGCARD): ADDRESS;
  147. VAR
  148.   Chunk: ADDRESS;
  149. BEGIN
  150.   Chunk := List^.NextFreeByte;
  151.   List^.NextFreeByte := ADDRESS(LONGCARD(List^.NextFreeByte) + Size);
  152.   List^.AmountLeft   := List^.AmountLeft - Size;
  153.   RETURN Chunk;
  154. END GetChunk;
  155.  
  156.  
  157. PROCEDURE LinkItem(List: Object; Item: ADDRESS);
  158. BEGIN
  159. (* Link it to first item in list *)
  160.   DynItem.LinkAfter(DynItem.Object(Item), List^.LastItem);
  161.  
  162.   List^.LastItem := DynItem.Object(Item);
  163.   IF ADDRESS(List^.FirstItem) = ADDRESS(NilDynItem) THEN
  164.     List^.FirstItem := DynItem.Object(Item);
  165.   END;
  166.   List^.ItemCount := List^.ItemCount + 1;
  167. END LinkItem;
  168.  
  169.  
  170. PROCEDURE Percolate(List: Object);
  171. VAR
  172.   MovedItem, OldItem: DynItem.Object;
  173.   NextAddr: ADDRESS;
  174.   ReclaimableSpace: LONGCARD;
  175. BEGIN
  176. (* If ItemCount is zero, then list is no longer needed;  reclaim it and
  177.    exit
  178. *)
  179.   IF List^.ItemCount = 0 THEN
  180.     UnlinkList(List);
  181.     DEALLOCATE(List, List^.Size);
  182.     RETURN;
  183.   END;
  184.  
  185. (* Move an item *)
  186.   OldItem   := List^.CurrentGapItem;
  187.   IF ADDRESS(OldItem) <> ADDRESS(NilDynItem) THEN
  188.     MovedItem := DynItem.MoveDown(OldItem);
  189.  
  190. (* Update list variables *)
  191.     IF ADDRESS(List^.FirstItem) = ADDRESS(OldItem) THEN
  192.       List^.FirstItem := MovedItem;
  193.     END;
  194.  
  195.     IF ADDRESS(List^.LastItem) = ADDRESS(OldItem) THEN
  196.       List^.LastItem := MovedItem;
  197.     END;
  198.  
  199.     IF ADDRESS(List^.LowGapItem) = ADDRESS(OldItem) THEN
  200.       List^.LowGapItem := DynItem.GetNext(MovedItem);
  201.     END;
  202.  
  203.     List^.CurrentGapItem := DynItem.GetNext(MovedItem);
  204.     IF ADDRESS(List^.CurrentGapItem) = ADDRESS(NilDynItem) THEN
  205.       List^.CurrentGapItem := List^.LowGapItem;
  206.     END;
  207.  
  208. (* Reclaim space between last item and first free byte *)
  209.     NextAddr := DynItem.NextAddr(List^.LastItem);
  210.     ReclaimableSpace := LONGCARD(List^.NextFreeByte - NextAddr);
  211.     List^.AmountLeft := List^.AmountLeft + ReclaimableSpace;
  212.     List^.NextFreeByte := NextAddr;
  213.   END;
  214. END Percolate;
  215.  
  216.  
  217. PROCEDURE UnlinkItem(List: Object; Item: ADDRESS);
  218. BEGIN
  219.   IF Item = ADDRESS(List^.LastItem) THEN
  220.     List^.LastItem := DynItem.GetPrev(DynItem.Object(Item));
  221.   END;
  222.  
  223.   IF Item = ADDRESS(List^.FirstItem) THEN
  224.     List^.FirstItem := DynItem.GetNext(DynItem.Object(Item));
  225.   END;
  226.  
  227.   IF (Item <= ADDRESS(List^.LowGapItem)) OR
  228.      (NIL  =  ADDRESS(List^.LowGapItem)) THEN
  229.     List^.LowGapItem := DynItem.GetNext(DynItem.Object(Item));
  230.   END;
  231.  
  232.   IF Item = ADDRESS(List^.CurrentGapItem) THEN
  233.     List^.CurrentGapItem := DynItem.GetNext(DynItem.Object(Item));
  234.   END;
  235.  
  236.   IF NIL = ADDRESS(List^.CurrentGapItem) THEN
  237.     List^.CurrentGapItem := List^.LowGapItem;
  238.   END;
  239.  
  240.   List^.ItemCount := List^.ItemCount - 1;
  241.  
  242.   DynItem.Unlink(DynItem.Object(Item));
  243. END UnlinkItem;
  244.  
  245.  
  246. PROCEDURE NextAddr(List: Object): ADDRESS;
  247. BEGIN
  248.   RETURN ADDRESS(LONGCARD(List) + ListRecordSize);
  249. END NextAddr;
  250.  
  251.  
  252. PROCEDURE DisposeAll();
  253. VAR
  254.   CurrentList, Temp: Object;
  255. BEGIN
  256.   CurrentList := FirstList;
  257.   LOOP
  258.     IF CurrentList = NIL THEN
  259.       EXIT;
  260.     END;
  261.     Temp := CurrentList^.NextList;
  262.     DEALLOCATE(CurrentList, CurrentList^.Size);
  263.     CurrentList := Temp;
  264.   END;
  265.   FirstList := NIL;
  266. END DisposeAll;
  267.  
  268.  
  269. PROCEDURE Nil(List: Object): BOOLEAN;
  270. BEGIN
  271.   RETURN (List = NIL);
  272. END Nil;
  273.  
  274.  
  275. BEGIN
  276.   FirstList := NIL;
  277.   ListRecordSize := WordAlign(TSIZE(ListRecord));
  278.   NilDynItem := DynItem.NilObject();
  279. END DynItemList.
  280.