[comp.sources.amiga] v90i115: HISM 1.0 - incremental storage manager for modula-2, Part01/01

Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator) (03/18/90)

Submitted-by: <dan-hankins@cup.portal.com>
Posting-number: Volume 90, Issue 115
Archive-name: examples/hism-1.0/part01

     This set of modules constitutes a storage manager with garbage
collection for Modula-2 programs.  It is written in TDI Modula-2 for the
Amiga, but should be easily portable to other implementations and
architectures.

#!/bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 1)."
# Contents:  Build.Rexx DynItem.def DynItem.mod DynItemList.def
#   DynItemList.mod DynTest.mod DynamicItem.def DynamicItem.mod
#   FreeHandle.def FreeHandle.mod HandleCollection.def
#   HandleCollection.mod README Storage.def Storage.mod WordAlign.def
#   WordAlign.mod
# Wrapped by tadguy@xanth on Sat Mar 17 15:33:16 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Build.Rexx' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Build.Rexx'\"
else
echo shar: Extracting \"'Build.Rexx'\" \(833 characters\)
sed "s/^X//" >'Build.Rexx' <<'END_OF_FILE'
X/**/
X
Xaddress command
Xcall erasefiles
Xcall addfiles
Xcall compilefiles
Xcall linkfile
X'dir *.er*'
Xexit 0
X
Xerasefiles:
X  'delete *.sym *.lnk *.er*'
Xreturn
X
Xaddfiles:
X  files = 0
X  call addfile 'DynItemList.def'
X  call addfile 'DynamicItem.def'
X  call addfile 'DynItem.def'
X  call addfile 'HandleCollection.def'
X  call addfile 'FreeHandle.def'
X  call addfile 'WordAlign.def'
X  call addfile 'Storage.def'
X
X  call addfile 'DynItemList'
X  call addfile 'DynamicItem'
X  call addfile 'DynItem'
X  call addfile 'HandleCollection'
X  call addfile 'FreeHandle'
X  call addfile 'WordAlign'
X  call addfile 'Storage'
X  call addfile 'DynTest'
Xreturn
X
Xaddfile:
X  parse arg filename
X  files = files + 1
X  infile.files = filename
Xreturn
X
Xcompilefiles:
X  do index = 1 to files
X    'modula' infile.index
X  end
Xreturn
X
X
Xlinkfile:
X  'link' infile.index
Xreturn
END_OF_FILE
if test 833 -ne `wc -c <'Build.Rexx'`; then
    echo shar: \"'Build.Rexx'\" unpacked with wrong size!
fi
# end of 'Build.Rexx'
fi
if test -f 'DynItem.def' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'DynItem.def'\"
else
echo shar: Extracting \"'DynItem.def'\" \(1462 characters\)
sed "s/^X//" >'DynItem.def' <<'END_OF_FILE'
XDEFINITION MODULE DynItem;
X
X(* Product: Incremental Storage Manager
X
X   Version: 1.0
X
X   Author:
X        Daniel B. Hankins
X        143 Montgomery Street
X        Poughkeepsie, NY 12601
X        dan-hankins@cup.portal.com
X
X   Creation Date: 1989
X
X   Release  Date: November 21, 1989
X
X   Notice of Intellectual Property:
X        This material is *NOT COPYRIGHTED*.  By this notice, I hereby place
X   this program and all its parts in the public domain, under the definitions
X   and restrictions of United States law.
X
X   History of Revisions:
X        None yet.
X*)
X
XFROM SYSTEM IMPORT ADDRESS;
X
XIMPORT DynamicItem;
XIMPORT DynItemList;
X
XTYPE
X  Object;
X
XPROCEDURE New(Size: LONGCARD; TermIt: DynamicItem.TermProc): Object;
X
XPROCEDURE Init(DObject: Object; InitIt: DynamicItem.InitProc);
X
XPROCEDURE SetHandle(DObject: Object; Handle: DynamicItem.Object);
X
XPROCEDURE Dispose(DObject: Object): BOOLEAN;
X
XPROCEDURE Kill(DObject: Object);
X
XPROCEDURE Ref(DObject: Object);
X
XPROCEDURE Access(DObject: Object): ADDRESS;
X
XPROCEDURE GetList(DObject: Object): DynItemList.Object;
X
XPROCEDURE Percolate(DObject: Object);
X
XPROCEDURE LinkAfter(DObjectNew, DObjectOld: Object);
X
XPROCEDURE Unlink(DObject: Object);
X
XPROCEDURE GetPrev(DObject: Object): Object;
X
XPROCEDURE GetNext(DObject: Object): Object;
X
XPROCEDURE MoveDown(DObject: Object): Object;
X
XPROCEDURE NextAddr(DObject: Object): ADDRESS;
X
XPROCEDURE NilObject(): Object;
X
XPROCEDURE Nil(DObject: Object): BOOLEAN;
X
XEND DynItem.
END_OF_FILE
if test 1462 -ne `wc -c <'DynItem.def'`; then
    echo shar: \"'DynItem.def'\" unpacked with wrong size!
fi
# end of 'DynItem.def'
fi
if test -f 'DynItem.mod' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'DynItem.mod'\"
else
echo shar: Extracting \"'DynItem.mod'\" \(5464 characters\)
sed "s/^X//" >'DynItem.mod' <<'END_OF_FILE'
XIMPLEMENTATION MODULE DynItem;
X
X(* Product: Incremental Storage Manager
X
X   Version: 1.0
X
X   Author:
X        Daniel B. Hankins
X        143 Montgomery Street
X        Poughkeepsie, NY 12601
X        dan-hankins@cup.portal.com
X
X   Creation Date: 1989
X
X   Release  Date: November 21, 1989
X
X   Notice of Intellectual Property:
X        This material is *NOT COPYRIGHTED*.  By this notice, I hereby place
X   this program and all its parts in the public domain, under the definitions
X   and restrictions of United States law.
X
X   History of Revisions:
X        None yet.
X*)
X
XFROM SYSTEM      IMPORT ADDRESS, TSIZE, WORD;
XFROM WordAlign   IMPORT WordAlign;
X
XIMPORT DynamicItem;
XIMPORT DynItemList;
X
XTYPE
X  Object  = POINTER TO Item;
X  WordPtr = POINTER TO WORD;
X
X  Item = RECORD
X           NextLower, NextHigher: Object;
X           Size, RefCount:        LONGCARD;
X           Term:                  DynamicItem.TermProc;
X           List:                  DynItemList.Object;
X           Handle:                DynamicItem.Object;
X         END;
X
XVAR
X  ItemTypeSize: LONGCARD;
X
X
XPROCEDURE New(Size: LONGCARD; TermIt: DynamicItem.TermProc): Object;
XVAR
X  NewObject: Object;
X  TotalSize: LONGCARD;
X  List:      DynItemList.Object;
XBEGIN
X(* New(Size, Object) <-
X     WordAlign(Size, Size),
X     Plus(Size, ItemTypeSize, TotalSize),
X     DynItemList.GetListWithSpace(TotalSize, List),
X     New2(TotalSize, List, Object).
X   New2(TotalSize, List, Object) <-
X     DynItemList.Nil(List),
X     SetValue(Object, NIL).
X   New2(TotalSize, List, Object) <-
X     DynItemList.GetChunk(List, TotalSize, NewObject),
X     SetValue(NewObject^.Size,     TotalSize),
X     SetValue(NewObject^.RefCount, 1),
X     SetValue(NewObject^.List,     List),
X     SetValue(NewObject^.Handle,   NIL),
X     DynItemList.LinkItem(List, NewObject),
X     SetValue(Object, NewObject).
X*)
X  Size      := WordAlign(Size);
X  TotalSize := Size + ItemTypeSize;
X  List      := DynItemList.GetListWithSpace(TotalSize);
X
X  IF DynItemList.Nil(List) THEN
X    RETURN(NIL);
X  END;
X
X  NewObject           := DynItemList.GetChunk(List, TotalSize);
X  NewObject^.Size     := TotalSize;
X  NewObject^.RefCount := 1;
X  NewObject^.List     := List;
X  NewObject^.Term     := TermIt;
X  DynItemList.LinkItem(List, NewObject);
X
X  RETURN NewObject;
XEND New;
X
X
XPROCEDURE Init(DObject: Object; InitIt: DynamicItem.InitProc);
XBEGIN
X  InitIt(Access(DObject));
XEND Init;
X
X
XPROCEDURE SetHandle(DObject: Object; Handle: DynamicItem.Object);
XBEGIN
X  DObject^.Handle := Handle;
XEND SetHandle;
X
X
XPROCEDURE Dispose(DObject: Object): BOOLEAN;
XBEGIN
X  DObject^.RefCount := DObject^.RefCount - 1;
X  IF DObject^.RefCount = 0 THEN
X    DObject^.Term(Access(DObject));
X    Kill(DObject);
X    RETURN TRUE;
X  END;
X  RETURN FALSE;
XEND Dispose;
X
X
XPROCEDURE Kill(DObject: Object);
XBEGIN
X  DynItemList.UnlinkItem(DObject^.List, DObject);
XEND Kill;
X
X
XPROCEDURE Ref(DObject: Object);
XBEGIN
X  DObject^.RefCount := DObject^.RefCount + 1;
XEND Ref;
X
X
XPROCEDURE Access(DObject: Object): ADDRESS;
XBEGIN
X  RETURN ADDRESS(LONGCARD(DObject) + ItemTypeSize);
XEND Access;
X
X
XPROCEDURE GetList(DObject: Object): DynItemList.Object;
XBEGIN
X  RETURN DObject^.List;
XEND GetList;
X
X
XPROCEDURE Percolate(DObject: Object);
XBEGIN
X  DynItemList.Percolate(DObject^.List);
XEND Percolate;
X
X
XPROCEDURE LinkAfter(DObjectNew, DObjectOld: Object);
XBEGIN
XIF DObjectOld <> NIL THEN
X  DObjectNew^.NextLower  := DObjectOld;
X  DObjectNew^.NextHigher := DObjectOld^.NextHigher;
X  DObjectNew^.NextLower^.NextHigher := DObjectNew;
X  IF DObjectNew^.NextHigher <> NIL THEN
X    DObjectNew^.NextHigher^.NextLower := DObjectNew;
X  END;
XELSE
X  DObjectNew^.NextLower := NIL;
X  DObjectNew^.NextHigher := NIL;
XEND;
XEND LinkAfter;
X
X
XPROCEDURE Unlink(DObject: Object);
XBEGIN
X  IF DObject^.NextLower <> NIL THEN
X    DObject^.NextLower^.NextHigher := DObject^.NextHigher;
X  END;
X  IF DObject^.NextHigher <> NIL THEN
X    DObject^.NextHigher^.NextLower := DObject^.NextLower;
X  END;
XEND Unlink;
X
X
XPROCEDURE GetPrev(DObject: Object): Object;
XBEGIN
X  RETURN DObject^.NextLower;
XEND GetPrev;
X
X
XPROCEDURE GetNext(DObject: Object): Object;
XBEGIN
X  RETURN DObject^.NextHigher;
XEND GetNext;
X
X
XPROCEDURE MoveDown(DObject: Object): Object;
X VAR
X  DestinationAddr: ADDRESS;
X  SourceWord, DestinationWord: WordPtr;
X  BytesToMove: LONGCARD;
XBEGIN
X  IF DObject^.NextLower = NIL THEN
X    DestinationAddr := DynItemList.NextAddr(DObject^.List);
X  ELSE
X    DestinationAddr := NextAddr(DObject^.NextLower);
X  END;
X
X  DynamicItem.Set(DObject^.Handle, DestinationAddr);
X
X  BytesToMove := DObject^.Size;
X  SourceWord := ADDRESS(DObject);
X  DestinationWord := DestinationAddr;
X
X  LOOP
X    IF BytesToMove = 0 THEN
X      EXIT;
X    END;
X    DestinationWord^ := SourceWord^;
X    DestinationWord  := ADDRESS(LONGCARD(DestinationWord) + 2);
X    SourceWord       := ADDRESS(LONGCARD(SourceWord) + 2);
X    BytesToMove      := BytesToMove - 2;
X  END;
X
X  DObject := DestinationAddr;
X
X  IF DObject^.NextLower <> NIL THEN
X    DObject^.NextLower^.NextHigher := DObject;
X  END;
X
X  IF DObject^.NextHigher <> NIL THEN
X    DObject^.NextHigher^.NextLower := DObject;
X  END;
X
X  RETURN Object(DestinationAddr);
XEND MoveDown;
X
X
XPROCEDURE NextAddr(DObject: Object): ADDRESS;
XBEGIN
X  RETURN ADDRESS(LONGCARD(DObject) + DObject^.Size);
XEND NextAddr;
X
X
XPROCEDURE NilObject(): Object;
XBEGIN
X  RETURN NIL;
XEND NilObject;
X
X
XPROCEDURE Nil(DObject: Object): BOOLEAN;
XBEGIN
X  RETURN (DObject = NIL);
XEND Nil;
X
X
XBEGIN
X  ItemTypeSize := WordAlign(TSIZE(Item));
XEND DynItem.
END_OF_FILE
if test 5464 -ne `wc -c <'DynItem.mod'`; then
    echo shar: \"'DynItem.mod'\" unpacked with wrong size!
fi
# end of 'DynItem.mod'
fi
if test -f 'DynItemList.def' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'DynItemList.def'\"
else
echo shar: Extracting \"'DynItemList.def'\" \(986 characters\)
sed "s/^X//" >'DynItemList.def' <<'END_OF_FILE'
XDEFINITION MODULE DynItemList;
X
X(* Product: Incremental Storage Manager
X
X   Version: 1.0
X
X   Author:
X        Daniel B. Hankins
X        143 Montgomery Street
X        Poughkeepsie, NY 12601
X        dan-hankins@cup.portal.com
X
X   Creation Date: 1989
X
X   Release  Date: November 21, 1989
X
X   Notice of Intellectual Property:
X        This material is *NOT COPYRIGHTED*.  By this notice, I hereby place
X   this program and all its parts in the public domain, under the definitions
X   and restrictions of United States law.
X
X   History of Revisions:
X        None yet.
X*)
X
XFROM SYSTEM IMPORT ADDRESS;
X
XTYPE
X  Object;
X
XPROCEDURE GetListWithSpace(Size: LONGCARD): Object;
X
XPROCEDURE GetChunk(List: Object; Size: LONGCARD): ADDRESS;
X
XPROCEDURE LinkItem(List: Object; Item: ADDRESS);
X
XPROCEDURE Percolate(List: Object);
X
XPROCEDURE UnlinkItem(List: Object; Item: ADDRESS);
X
XPROCEDURE NextAddr(List: Object): ADDRESS;
X
XPROCEDURE DisposeAll();
X
XPROCEDURE Nil(List: Object): BOOLEAN;
X
XEND DynItemList.
END_OF_FILE
if test 986 -ne `wc -c <'DynItemList.def'`; then
    echo shar: \"'DynItemList.def'\" unpacked with wrong size!
fi
# end of 'DynItemList.def'
fi
if test -f 'DynItemList.mod' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'DynItemList.mod'\"
else
echo shar: Extracting \"'DynItemList.mod'\" \(6556 characters\)
sed "s/^X//" >'DynItemList.mod' <<'END_OF_FILE'
XIMPLEMENTATION MODULE DynItemList;
X
X(* Product: Incremental Storage Manager
X
X   Version: 1.0
X
X   Author:
X        Daniel B. Hankins
X        143 Montgomery Street
X        Poughkeepsie, NY 12601
X        dan-hankins@cup.portal.com
X
X   Creation Date: 1989
X
X   Release  Date: November 21, 1989
X
X   Notice of Intellectual Property:
X        This material is *NOT COPYRIGHTED*.  By this notice, I hereby place
X   this program and all its parts in the public domain, under the definitions
X   and restrictions of United States law.
X
X   History of Revisions:
X        None yet.
X*)
X
XFROM SYSTEM    IMPORT ADDRESS, TSIZE;
XFROM WordAlign IMPORT WordAlign;
XFROM Storage   IMPORT ALLOCATE, DEALLOCATE;
X
XIMPORT DynItem;
X
XTYPE
X  Object     = POINTER TO ListRecord;
X  ListRecord = RECORD
X                 PrevList, NextList:          Object;
X                 NextFreeByte:                ADDRESS;
X                 AmountLeft, ItemCount, Size: LONGCARD;
X                 FirstItem, LastItem,
X                 LowGapItem, CurrentGapItem:  DynItem.Object;
X               END;
X
XVAR
X  FirstList:      Object;
X  ListRecordSize: LONGCARD;
X  NilDynItem:     DynItem.Object;
X
XCONST
X  BlockSizeResolution = 1024;
X
X
XPROCEDURE GetListWithSpace(Size: LONGCARD): Object;
XVAR
X  NewList: Object;
XBEGIN
X  IF FirstList = NIL THEN
X    FirstList := New(Size);
X    RETURN FirstList;
X  END;
X
X  NewList := FindListWithSpace(FirstList, Size);
X  IF NewList <> NIL THEN
X    RETURN NewList;
X  END;
X
X  NewList := New(Size);
X  IF NewList = NIL THEN
X    RETURN NIL;
X  END;
X
X  LinkInList(NewList, FirstList);
X  RETURN NewList;
XEND GetListWithSpace;
X
X
XPROCEDURE New(Size: LONGCARD): Object;
XVAR
X  NewObject: Object;
XBEGIN
X  Size := Size + ListRecordSize;
X  Size := ((Size - 1) DIV BlockSizeResolution + 1) * BlockSizeResolution;
X  ALLOCATE(NewObject, Size);
X  IF NewObject = NIL THEN
X    RETURN NIL;
X  END;
X  NewObject^.PrevList     := NIL;
X  NewObject^.NextList     := NIL;
X  NewObject^.AmountLeft   := Size - ListRecordSize;
X  NewObject^.Size         := Size;
X  NewObject^.NextFreeByte := ADDRESS(LONGCARD(NewObject) + ListRecordSize);
X  NewObject^.FirstItem      := NilDynItem;
X  NewObject^.LastItem       := NilDynItem;
X  NewObject^.LowGapItem     := NilDynItem;
X  NewObject^.CurrentGapItem := NilDynItem;
X  RETURN NewObject;
XEND New;
X
X
XPROCEDURE FindListWithSpace(List: Object; Size: LONGCARD): Object;
XBEGIN
X  LOOP
X    IF List = NIL THEN
X      RETURN NIL;
X    END;
X
X    IF List^.AmountLeft >= Size THEN
X      RETURN List;
X    END;
X
X    List := List^.NextList;
X  END;
XEND FindListWithSpace;
X
X
XPROCEDURE LinkInList(NewList: Object; OldList: Object);
XBEGIN
X  IF OldList <> NIL THEN
X    NewList^.PrevList := OldList;
X    NewList^.NextList := OldList^.NextList;
X    NewList^.PrevList^.NextList := NewList;
X    IF NewList^.NextList <> NIL THEN
X      NewList^.NextList^.PrevList := NewList;
X    END;
X  ELSE
X    NewList^.PrevList := NIL;
X    NewList^.NextList := NIL;
X  END;
XEND LinkInList;
X
X
XPROCEDURE UnlinkList(List: Object);
XBEGIN
X  IF List^.PrevList <> NIL THEN
X    List^.PrevList^.NextList := List^.NextList;
X  END;
X
X  IF List^.NextList <> NIL THEN
X    List^.NextList^.PrevList := List^.PrevList;
X  END;
X
X  IF List = FirstList THEN
X    FirstList := List^.NextList;
X  END;
XEND UnlinkList;
X
X
XPROCEDURE GetChunk(List: Object; Size: LONGCARD): ADDRESS;
XVAR
X  Chunk: ADDRESS;
XBEGIN
X  Chunk := List^.NextFreeByte;
X  List^.NextFreeByte := ADDRESS(LONGCARD(List^.NextFreeByte) + Size);
X  List^.AmountLeft   := List^.AmountLeft - Size;
X  RETURN Chunk;
XEND GetChunk;
X
X
XPROCEDURE LinkItem(List: Object; Item: ADDRESS);
XBEGIN
X(* Link it to first item in list *)
X  DynItem.LinkAfter(DynItem.Object(Item), List^.LastItem);
X
X  List^.LastItem := DynItem.Object(Item);
X  IF ADDRESS(List^.FirstItem) = ADDRESS(NilDynItem) THEN
X    List^.FirstItem := DynItem.Object(Item);
X  END;
X  List^.ItemCount := List^.ItemCount + 1;
XEND LinkItem;
X
X
XPROCEDURE Percolate(List: Object);
XVAR
X  MovedItem, OldItem: DynItem.Object;
X  NextAddr: ADDRESS;
X  ReclaimableSpace: LONGCARD;
XBEGIN
X(* If ItemCount is zero, then list is no longer needed;  reclaim it and
X   exit
X*)
X  IF List^.ItemCount = 0 THEN
X    UnlinkList(List);
X    DEALLOCATE(List, List^.Size);
X    RETURN;
X  END;
X
X(* Move an item *)
X  OldItem   := List^.CurrentGapItem;
X  IF ADDRESS(OldItem) <> ADDRESS(NilDynItem) THEN
X    MovedItem := DynItem.MoveDown(OldItem);
X
X(* Update list variables *)
X    IF ADDRESS(List^.FirstItem) = ADDRESS(OldItem) THEN
X      List^.FirstItem := MovedItem;
X    END;
X
X    IF ADDRESS(List^.LastItem) = ADDRESS(OldItem) THEN
X      List^.LastItem := MovedItem;
X    END;
X
X    IF ADDRESS(List^.LowGapItem) = ADDRESS(OldItem) THEN
X      List^.LowGapItem := DynItem.GetNext(MovedItem);
X    END;
X
X    List^.CurrentGapItem := DynItem.GetNext(MovedItem);
X    IF ADDRESS(List^.CurrentGapItem) = ADDRESS(NilDynItem) THEN
X      List^.CurrentGapItem := List^.LowGapItem;
X    END;
X
X(* Reclaim space between last item and first free byte *)
X    NextAddr := DynItem.NextAddr(List^.LastItem);
X    ReclaimableSpace := LONGCARD(List^.NextFreeByte - NextAddr);
X    List^.AmountLeft := List^.AmountLeft + ReclaimableSpace;
X    List^.NextFreeByte := NextAddr;
X  END;
XEND Percolate;
X
X
XPROCEDURE UnlinkItem(List: Object; Item: ADDRESS);
XBEGIN
X  IF Item = ADDRESS(List^.LastItem) THEN
X    List^.LastItem := DynItem.GetPrev(DynItem.Object(Item));
X  END;
X
X  IF Item = ADDRESS(List^.FirstItem) THEN
X    List^.FirstItem := DynItem.GetNext(DynItem.Object(Item));
X  END;
X
X  IF (Item <= ADDRESS(List^.LowGapItem)) OR
X     (NIL  =  ADDRESS(List^.LowGapItem)) THEN
X    List^.LowGapItem := DynItem.GetNext(DynItem.Object(Item));
X  END;
X
X  IF Item = ADDRESS(List^.CurrentGapItem) THEN
X    List^.CurrentGapItem := DynItem.GetNext(DynItem.Object(Item));
X  END;
X
X  IF NIL = ADDRESS(List^.CurrentGapItem) THEN
X    List^.CurrentGapItem := List^.LowGapItem;
X  END;
X
X  List^.ItemCount := List^.ItemCount - 1;
X
X  DynItem.Unlink(DynItem.Object(Item));
XEND UnlinkItem;
X
X
XPROCEDURE NextAddr(List: Object): ADDRESS;
XBEGIN
X  RETURN ADDRESS(LONGCARD(List) + ListRecordSize);
XEND NextAddr;
X
X
XPROCEDURE DisposeAll();
XVAR
X  CurrentList, Temp: Object;
XBEGIN
X  CurrentList := FirstList;
X  LOOP
X    IF CurrentList = NIL THEN
X      EXIT;
X    END;
X    Temp := CurrentList^.NextList;
X    DEALLOCATE(CurrentList, CurrentList^.Size);
X    CurrentList := Temp;
X  END;
X  FirstList := NIL;
XEND DisposeAll;
X
X
XPROCEDURE Nil(List: Object): BOOLEAN;
XBEGIN
X  RETURN (List = NIL);
XEND Nil;
X
X
XBEGIN
X  FirstList := NIL;
X  ListRecordSize := WordAlign(TSIZE(ListRecord));
X  NilDynItem := DynItem.NilObject();
XEND DynItemList.
END_OF_FILE
if test 6556 -ne `wc -c <'DynItemList.mod'`; then
    echo shar: \"'DynItemList.mod'\" unpacked with wrong size!
fi
# end of 'DynItemList.mod'
fi
if test -f 'DynTest.mod' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'DynTest.mod'\"
else
echo shar: Extracting \"'DynTest.mod'\" \(6342 characters\)
sed "s/^X//" >'DynTest.mod' <<'END_OF_FILE'
XMODULE DynTest;
X
X(* Product: Incremental Storage Manager
X
X   Version: 1.0
X
X   Author:
X        Daniel B. Hankins
X        143 Montgomery Street
X        Poughkeepsie, NY 12601
X        dan-hankins@cup.portal.com
X
X   Creation Date: 1989
X
X   Release  Date: November 21, 1989
X
X   Notice of Intellectual Property:
X        This material is *NOT COPYRIGHTED*.  By this notice, I hereby place
X   this program and all its parts in the public domain, under the definitions
X   and restrictions of United States law.
X
X   History of Revisions:
X        None yet.
X*)
X
XFROM SYSTEM        IMPORT ADDRESS;
XFROM DOSProcessHandler IMPORT Exit;
XFROM RandomNumbers IMPORT Seed, Random;
XFROM InOut         IMPORT WriteString, WriteCard, WriteLn;
XFROM LongInOut     IMPORT WriteLongCard;
X
XIMPORT DynamicItem;
XIMPORT Strings;
X
X(*
XFROM Debug         IMPORT DebugFlag;
X*)
X
X
XTYPE
X  Transparent = POINTER TO LONGCARD;
X  StrPtr = POINTER TO Strings.String;
X
XCONST
X  ArraySize = 50;
X
XVAR
X  ArrayIndex: CARDINAL;
X  TempIndex, Index: LONGCARD;
X  TestArray: ARRAY [1..ArraySize] OF RECORD
X                                       count: CARDINAL;
X                                       size:  LONGCARD;
X                                       ref:   DynamicItem.Object;
X                                     END;
X  ItemVar: Transparent;
X  Prose, Temp1, Temp2: Strings.String;
X  Comp: Strings.CompareResults;
X  NewString: StrPtr;
X
X
XPROCEDURE DoesNothing(NotUsed: ADDRESS);
XBEGIN
XEND DoesNothing;
X
X
XBEGIN
X  TempIndex := 1;
X  Seed(314);
X  Prose := 'Four-score-and-seven-years-ago,-our-forefathers...Dont-sell';
X  Strings.Concat(Prose, 
X           '-Shell-Sort-short.-Did-I-say-something-wrong?--Pardon-me-for',
X           Prose);
X  Strings.Concat(Prose,
X           '-breathing-which-I-never-do-anyway-so-I-dont-know-why-I-bother',
X           Prose);
X  Strings.Concat(Prose,
X           '-to-say-it-oh-god-im-so-depressed.--Life?-Dont-talk-to-me-about',
X           Prose);
X
X  FOR ArrayIndex := 1 TO ArraySize DO
X    TestArray[ArrayIndex].ref      := DynamicItem.NilObject();
X    TestArray[ArrayIndex].count    := 0;
X    TestArray[ArrayIndex].size     := LONG(0);
X  END;
X  WriteString("Finished initialization.");
X  WriteLn;
X  FOR Index := 1 TO 2500 DO
X    IF FALSE = TRUE THEN
X      (* DebugFlag := TRUE; *)
X    END;
X    ArrayIndex := Random(ArraySize) + 1;
X    WriteLn;
X    IF Random(TestArray[ArrayIndex].count+2) = 0 THEN
X      IF TestArray[ArrayIndex].count > 0 THEN
X        WriteLongCard(Index + 25 * (TempIndex - 1), 5); WriteString(': ');
X        WriteString("Adding ref to item");
X        WriteCard(ArrayIndex,10); WriteString("."); WriteLn;
X
X        ItemVar := Transparent(TestArray[ArrayIndex].ref);
X        TestArray[ArrayIndex].ref :=
X          DynamicItem.Ref(TestArray[ArrayIndex].ref);
X        TestArray[ArrayIndex].count := TestArray[ArrayIndex].count + 1;
X
X        NewString := DynamicItem.Access(TestArray[ArrayIndex].ref);
X        Strings.Assign(Temp1, NewString^);
X        Strings.Assign(Temp2,'');
X        Strings.Copy(Prose, 0,
X                     SHORT(TestArray[ArrayIndex].size)-1, Temp2);
X        Comp := Strings.Compare(Temp1, Temp2);
X        IF NOT(Comp = Strings.Equal) THEN
X          WriteString("Error in comparison."); WriteLn();
X          Exit(0);
X        END;
X
X        WriteString("Ref, Item, Count, Size =");
X        WriteLongCard(LONGCARD(TestArray[ArrayIndex].ref),10);
X        ItemVar := Transparent(TestArray[ArrayIndex].ref);
X        WriteLongCard(ItemVar^,11);
X        WriteCard(TestArray[ArrayIndex].count,10);
X        WriteLongCard(TestArray[ArrayIndex].size,10);
X        WriteLn;
X      ELSE
X        WriteLongCard(Index + 25 * (TempIndex - 1), 5); WriteString(': ');
X        WriteString("Getting new item");
X        WriteCard(ArrayIndex,10); WriteString("."); WriteLn;
X
X        TestArray[ArrayIndex].size := LONG(Random(200) + 1);
X
X        WriteString("Size is"); WriteLongCard(TestArray[ArrayIndex].size, 10);
X        WriteLn;
X
X        ItemVar := Transparent(TestArray[ArrayIndex].ref);
X        TestArray[ArrayIndex].ref :=
X          DynamicItem.New(TestArray[ArrayIndex].size, DoesNothing, DoesNothing);
X
X        IF NOT(DynamicItem.Nil(TestArray[ArrayIndex].ref)) THEN
X          NewString := StrPtr(DynamicItem.Access(TestArray[ArrayIndex].ref));
X          Strings.Copy(Prose, 0,
X                       SHORT(TestArray[ArrayIndex].size)-1, NewString^);
X
X          WriteString("Got new item."); WriteLn;
X
X          TestArray[ArrayIndex].count := TestArray[ArrayIndex].count + 1;
X
X          WriteString("Ref, Item, Count, Size =");
X          WriteLongCard(LONGCARD(TestArray[ArrayIndex].ref),10);
X          ItemVar := Transparent(TestArray[ArrayIndex].ref);
X          WriteLongCard(ItemVar^,11);
X          WriteCard(TestArray[ArrayIndex].count,10);
X          WriteLongCard(TestArray[ArrayIndex].size,10);
X          WriteLn;
X        ELSE
X          WriteString("No more space!");
X          WriteLn;
X          Exit(0);
X        END;
X      END;
X    ELSE
X      IF TestArray[ArrayIndex].count > 0 THEN
X        WriteLongCard(Index + 25 * (TempIndex - 1), 5); WriteString(': ');
X        WriteString("Getting rid of item");
X        WriteCard(ArrayIndex,10); WriteString("."); WriteLn;
X
X        NewString := DynamicItem.Access(TestArray[ArrayIndex].ref);
X        Strings.Assign(Temp1, NewString^);
X        Strings.Assign(Temp2,'');
X        Strings.Copy(Prose, 0,
X                     SHORT(TestArray[ArrayIndex].size)-1, Temp2);
X        Comp := Strings.Compare(Temp1, Temp2);
X        IF NOT(Comp = Strings.Equal) THEN
X          WriteString("Error in comparison."); WriteLn();
X          Exit(0);
X        END;
X
X        ItemVar := Transparent(TestArray[ArrayIndex].ref);
X        DynamicItem.Dispose(TestArray[ArrayIndex].ref);
X        TestArray[ArrayIndex].count := TestArray[ArrayIndex].count - 1;
X
X        WriteString("Ref, Item, Count, Size =");
X        WriteLongCard(LONGCARD(TestArray[ArrayIndex].ref),10);
X        ItemVar := Transparent(TestArray[ArrayIndex].ref);
X        WriteLongCard(ItemVar^,11);
X        WriteCard(TestArray[ArrayIndex].count,10);
X        WriteLongCard(TestArray[ArrayIndex].size,10);
X        WriteLn;
X      ELSE
X        WriteString("No item yet at index");
X        WriteCard(ArrayIndex,10); WriteString("."); WriteLn;
X      END;
X    END;
X  END;
X  DynamicItem.DisposeAll();
X  WriteString("Finished test.");
X  WriteLn;
XEND DynTest.
END_OF_FILE
if test 6342 -ne `wc -c <'DynTest.mod'`; then
    echo shar: \"'DynTest.mod'\" unpacked with wrong size!
fi
# end of 'DynTest.mod'
fi
if test -f 'DynamicItem.def' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'DynamicItem.def'\"
else
echo shar: Extracting \"'DynamicItem.def'\" \(5796 characters\)
sed "s/^X//" >'DynamicItem.def' <<'END_OF_FILE'
XDEFINITION MODULE DynamicItem;
X
X(* Product: Incremental Storage Manager
X
X   Version: 1.0
X
X   Author:
X        Daniel B. Hankins
X        143 Montgomery Street
X        Poughkeepsie, NY 12601
X        dan-hankins@cup.portal.com
X
X   Creation Date: 1989
X
X   Release  Date: November 21, 1989
X
X   Notice of Intellectual Property:
X        This material is *NOT COPYRIGHTED*.  By this notice, I hereby place
X   this program and all its parts in the public domain, under the definitions
X   and restrictions of United States law.
X
X   History of Revisions:
X        None yet.
X*)
X
XFROM SYSTEM IMPORT ADDRESS;
X
XTYPE
X  Object;
X
X  InitProc = PROCEDURE(ADDRESS);
X  TermProc = InitProc;
X
XPROCEDURE New(Size: LONGCARD; InitIt: InitProc; TermIt: TermProc): Object;
X(* Size:   *in*  Size in bytes of chunk to be allocated
X   InitIt: *in*  The procedure which will initialize the contents of the
X                 chunk.  It is passed the address of the first byte of the
X                 chunk.
X   TermIt: *in*  The procedure which will clean up the contents of the
X                 chunk when its storage is reclaimed.  For instance, if
X                 the chunk contains variables of type DynamicItem.Object,
X                 TermIt should DynamicItem.Dispose each of them so that
X                 their reference counts can be accurately maintained.
X           *out* The resulting object
X*)
X
XPROCEDURE Ref(Item: Object): Object;
X(* Item: *in*  The chunk to which another reference is to be generated.
X         *out* The chunk after its reference count is incremented.
X
X   Explanations and Recommendations:
X        Although the Modula-2 compiler will allow the programmer to perform
X   assignment between variables of type DynamicItem.Object, she should not.
X   This storage manager relies on a technique called reference counts.  The
X   reference count (which is embedded in the header of a storage chunk) is
X   intended to reflect the number of variables (pointers, actually) which
X   are accessing the same chunk.  The reason for this is so that the
X   storage manager will know when it can remove the chunk from the active
X   list and reclaim the storage it consumed.
X        So if variables A, B, and C are all of type DynamicItem.Object, and
X   all reference the same storage chunk, then the reference count of the
X   chunk should be three.
X        To make two variables refer to the same object, use the following:
X
X        A := DynamicItem.Ref(B);
X
X   instead of
X
X        A := B;
X
X        If you want to copy the contents of an chunk A into another chunk
X   B, then the programmer should create a new dynamic item object B, access
X   the contents of both, and then copy the contents.  For instance:
X
X        B := DynamicItem.New(ASize, AInit, ATerm);
X        ACopy(DynamicItem.Access(A), DynamicItem.Access(B));
X
X   where ACopy takes a pair of pointers to the kind of chunk being copied.
X*)
X
X
XPROCEDURE Dispose(Item: Object);
X(* Item: *in* The chunk to be disposed of.
X
X   Explanations and Recommendations:
X        Dispose does *not* necessarily reclaim the storage used by a chunk.
X   Dispose decrements the reference count of the chunk (see procedure Ref,
X   above); there is now one less pointer to the chunk.  Only when there are
X   no pointers left to a chunk (i.e. reference count = 0) does Dispose
X   actually attempt to reclaim the storage used by the chunk.  Just
X   before reclaiming that storage, it runs the TermIt procedure (see
X   procedure New, above) stored in the header of the chunk against the
X   contents of that chunk.  The TermIt procedure is meant to be used for
X   Dispose-ing of any chunks the chunk may reference.
X        For instance, suppose that the chunk the programmer is working
X   with is a record which has three variables of type DynamicItem.Object.
X   TermIt should DynamicItem.Dispose each of the three variables.
X   Otherwise, the three chunks referenced will *never* be reclaimed;
X   their reference counts will never go to zero, and they will become
X   unusable dead storage.
X*)
X
XPROCEDURE Access(Item: Object): ADDRESS;
X(* Item: *in*   The chunk which is to be accessed.
X         *out*  The address of the contents of the chunk.
X
X   Explanations and Recommendations:
X        Whenever DynamicItem.New or DynamicItem.Dispose is called,
X   the contents of a chunk may move in memory.  So it is a good idea to
X   avoid code like this:
X
X        ChunkPtr := DynamicItem.Access(ChunkVar);
X        ...
X        (* other code *)
X        ...
X        DynamicItem.Dispose(ChunkVar2);
X        ChunkPtr^.XValue := 10;
X
X   because ChunkPtr may no longer be pointing at the contents of the
X   chunk after a New or Dispose is done.  A better practice is to
X   *always* Access a chunk *just before* its contents are to be
X   manipulated, like this:
X
X        ChunkPtr := DynamicItem.Access(ChunkVar);
X        ...
X        (* other code *)
X        ...
X        DynamicItem.Dispose(ChunkVar2);
X>>>     ChunkPtr := DynamicItem.Access(ChunkVar);
X        ChunkPtr^.XValue := 10;
X*)
X
XPROCEDURE Set(Item:Object; NewDynItem: ADDRESS);
X(* DO NOT USE THIS PROCEDURE; IT IS FOR THE EXCLUSIVE USE OF OTHER PARTS
X   OF THE STORAGE MANAGER!
X*)
X
XPROCEDURE DisposeAll();
X(* This procedure returns *all* storage allocated by the storage manager
X   to the operating system.  It is a good idea to call this procedure
X   just before exiting your program;  it makes sure you haven't forgotten
X   to return any resources you've used.
X*)
X
XPROCEDURE NilObject(): Object;
X(* This procedure returns an uninitialized chunk, which cannot be used
X   except for testing to see if another chunk is uninitialized.  It is
X   primarily for use of other storage manager procedures.
X*)
X
XPROCEDURE Nil(Item: Object): BOOLEAN;
X(* This procedure returns TRUE if a chunk is uninitialized, FALSE 
X   otherwise.
X*)
X
XEND DynamicItem.
END_OF_FILE
if test 5796 -ne `wc -c <'DynamicItem.def'`; then
    echo shar: \"'DynamicItem.def'\" unpacked with wrong size!
fi
# end of 'DynamicItem.def'
fi
if test -f 'DynamicItem.mod' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'DynamicItem.mod'\"
else
echo shar: Extracting \"'DynamicItem.mod'\" \(2748 characters\)
sed "s/^X//" >'DynamicItem.mod' <<'END_OF_FILE'
XIMPLEMENTATION MODULE DynamicItem;
X
X(* Product: Incremental Storage Manager
X
X   Version: 1.0
X
X   Author:
X        Daniel B. Hankins
X        143 Montgomery Street
X        Poughkeepsie, NY 12601
X        dan-hankins@cup.portal.com
X
X   Creation Date: 1989
X
X   Release  Date: November 21, 1989
X
X   Notice of Intellectual Property:
X        This material is *NOT COPYRIGHTED*.  By this notice, I hereby place
X   this program and all its parts in the public domain, under the definitions
X   and restrictions of United States law.
X
X   History of Revisions:
X        None yet.
X*)
X
XFROM SYSTEM      IMPORT ADDRESS, TSIZE;
X
XIMPORT HandleCollection;
XIMPORT DynItem;
XIMPORT DynItemList;
X
XTYPE
X  Object = POINTER TO Handle;
X  Handle = DynItem.Object;
X
X
XPROCEDURE New(Size: LONGCARD; InitIt: InitProc; TermIt: TermProc): Object;
XVAR
X  DItem:      Object;
X  ItemHandle: Handle;
XBEGIN
X(* New(Size, InitIt, Item) <-
X     DynItem.New(Size, ItemHandle),
X     New2(ItemHandle, InitIt, Item).
X   New2(ItemHandle, InitIt, Item) <-
X     DynItem.Nil(ItemHandle),
X     SetValue(Item,NIL).
X   New2(ItemHandle, InitIt, Item) <-
X     HandleCollection.NewHandle(DItem),
X     New3(ItemHandle, DItem, InitIt, Item).
X   New3(ItemHandle, DItem, InitIt, Item) <-
X     EqualValue(DItem, NIL),
X     DynItem.Kill(ItemHandle),
X     SetValue(Item, NIL).
X   New3(ItemHandle, DItem, InitIt, Item) <-
X     SetValue(DItem^, ItemHandle),
X     DynItem.SetHandle(DItem^, DItem),
X     DynItem.Percolate(DItem^),
X     DynItem.Percolate(DItem^),
X     DynItem.Init(DItem^, InitIt),
X     SetValue(Item, DItem).
X*)
X  ItemHandle := DynItem.New(Size, TermIt);
X  IF DynItem.Nil(ItemHandle) THEN
X    RETURN NIL;
X  END;
X
X  DItem := HandleCollection.NewHandle();
X  IF DItem = NIL THEN
X    DynItem.Kill(ItemHandle);
X    RETURN NIL;
X  END;
X
X  DItem^ := ItemHandle;
X  DynItem.SetHandle(DItem^, DItem);
X  DynItem.Percolate(DItem^);
X  DynItem.Percolate(DItem^);
X  DynItem.Init(DItem^, InitIt);
X
X  RETURN DItem;
XEND New;
X
X
XPROCEDURE Ref(Item: Object): Object;
XBEGIN
X  DynItem.Ref(Item^);
X  RETURN Item;
XEND Ref;
X
X
XPROCEDURE Dispose(Item: Object);
XVAR
X  List: DynItemList.Object;
XBEGIN
X  List := DynItem.GetList(Item^);
X  IF DynItem.Dispose(Item^) THEN
X    HandleCollection.DisposeHandle(Item);
X  END;
X  DynItemList.Percolate(List);
XEND Dispose;
X
X
XPROCEDURE Access(Item: Object): ADDRESS;
XBEGIN
X  RETURN DynItem.Access(Item^);
XEND Access;
X
X
XPROCEDURE Set(Item:Object; NewDynItem: ADDRESS);
XBEGIN
X  Item^ := DynItem.Object(NewDynItem);
XEND Set;
X
X
XPROCEDURE DisposeAll();
XBEGIN
X  DynItemList.DisposeAll();
X  HandleCollection.DisposeAll();
XEND DisposeAll;
X
X
XPROCEDURE NilObject(): Object;
XBEGIN
X  RETURN NIL;
XEND NilObject;
X
X
XPROCEDURE Nil(Item: Object): BOOLEAN;
XBEGIN
X  RETURN (Item = NIL);
XEND Nil;
X
XEND DynamicItem.
END_OF_FILE
if test 2748 -ne `wc -c <'DynamicItem.mod'`; then
    echo shar: \"'DynamicItem.mod'\" unpacked with wrong size!
fi
# end of 'DynamicItem.mod'
fi
if test -f 'FreeHandle.def' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'FreeHandle.def'\"
else
echo shar: Extracting \"'FreeHandle.def'\" \(714 characters\)
sed "s/^X//" >'FreeHandle.def' <<'END_OF_FILE'
XDEFINITION MODULE FreeHandle;
X
X(* Product: Incremental Storage Manager
X
X   Version: 1.0
X
X   Author:
X        Daniel B. Hankins
X        143 Montgomery Street
X        Poughkeepsie, NY 12601
X        dan-hankins@cup.portal.com
X
X   Creation Date: 1989
X
X   Release  Date: November 21, 1989
X
X   Notice of Intellectual Property:
X        This material is *NOT COPYRIGHTED*.  By this notice, I hereby place
X   this program and all its parts in the public domain, under the definitions
X   and restrictions of United States law.
X
X   History of Revisions:
X        None yet.
X*)
X
XTYPE
X  Object;
X
XPROCEDURE Next(FHObject: Object): Object;
X
XPROCEDURE NilObject(): Object;
X
XPROCEDURE Nil(FHObject: Object): BOOLEAN;
X
XEND FreeHandle.
END_OF_FILE
if test 714 -ne `wc -c <'FreeHandle.def'`; then
    echo shar: \"'FreeHandle.def'\" unpacked with wrong size!
fi
# end of 'FreeHandle.def'
fi
if test -f 'FreeHandle.mod' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'FreeHandle.mod'\"
else
echo shar: Extracting \"'FreeHandle.mod'\" \(904 characters\)
sed "s/^X//" >'FreeHandle.mod' <<'END_OF_FILE'
XIMPLEMENTATION MODULE FreeHandle;
X
X(* Product: Incremental Storage Manager
X
X   Version: 1.0
X
X   Author:
X        Daniel B. Hankins
X        143 Montgomery Street
X        Poughkeepsie, NY 12601
X        dan-hankins@cup.portal.com
X
X   Creation Date: 1989
X
X   Release  Date: November 21, 1989
X
X   Notice of Intellectual Property:
X        This material is *NOT COPYRIGHTED*.  By this notice, I hereby place
X   this program and all its parts in the public domain, under the definitions
X   and restrictions of United States law.
X
X   History of Revisions:
X        None yet.
X*)
X
XTYPE
X  Object           = POINTER TO FreeHandleObject;
X  FreeHandleObject = Object;
X
X
XPROCEDURE Next(FHObject: Object): Object;
XBEGIN
X  RETURN FHObject^;
XEND Next;
X
X
XPROCEDURE NilObject(): Object;
XBEGIN
X  RETURN NIL;
XEND NilObject;
X
X
XPROCEDURE Nil(FHObject: Object): BOOLEAN;
XBEGIN
X  RETURN (FHObject = NIL);
XEND Nil;
X
X
XEND FreeHandle.
END_OF_FILE
if test 904 -ne `wc -c <'FreeHandle.mod'`; then
    echo shar: \"'FreeHandle.mod'\" unpacked with wrong size!
fi
# end of 'FreeHandle.mod'
fi
if test -f 'HandleCollection.def' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'HandleCollection.def'\"
else
echo shar: Extracting \"'HandleCollection.def'\" \(721 characters\)
sed "s/^X//" >'HandleCollection.def' <<'END_OF_FILE'
XDEFINITION MODULE HandleCollection;
X
X(* Product: Incremental Storage Manager
X
X   Version: 1.0
X
X   Author:
X        Daniel B. Hankins
X        143 Montgomery Street
X        Poughkeepsie, NY 12601
X        dan-hankins@cup.portal.com
X
X   Creation Date: 1989
X
X   Release  Date: November 21, 1989
X
X   Notice of Intellectual Property:
X        This material is *NOT COPYRIGHTED*.  By this notice, I hereby place
X   this program and all its parts in the public domain, under the definitions
X   and restrictions of United States law.
X
X   History of Revisions:
X        None yet.
X*)
X
XFROM SYSTEM  IMPORT ADDRESS;
X
XPROCEDURE NewHandle(): ADDRESS;
X
XPROCEDURE DisposeHandle(Item: ADDRESS);
X
XPROCEDURE DisposeAll();
X
XEND HandleCollection.
END_OF_FILE
if test 721 -ne `wc -c <'HandleCollection.def'`; then
    echo shar: \"'HandleCollection.def'\" unpacked with wrong size!
fi
# end of 'HandleCollection.def'
fi
if test -f 'HandleCollection.mod' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'HandleCollection.mod'\"
else
echo shar: Extracting \"'HandleCollection.mod'\" \(2997 characters\)
sed "s/^X//" >'HandleCollection.mod' <<'END_OF_FILE'
XIMPLEMENTATION MODULE HandleCollection;
X
X(* Product: Incremental Storage Manager
X
X   Version: 1.0
X
X   Author:
X        Daniel B. Hankins
X        143 Montgomery Street
X        Poughkeepsie, NY 12601
X        dan-hankins@cup.portal.com
X
X   Creation Date: 1989
X
X   Release  Date: November 21, 1989
X
X   Notice of Intellectual Property:
X        This material is *NOT COPYRIGHTED*.  By this notice, I hereby place
X   this program and all its parts in the public domain, under the definitions
X   and restrictions of United States law.
X
X   History of Revisions:
X        None yet.
X*)
X
XFROM SYSTEM  IMPORT ADDRESS, TSIZE, ADR;
XFROM Storage IMPORT ALLOCATE, DEALLOCATE;
X
XIMPORT DynamicItem;
XIMPORT FreeHandle;
X
XCONST
X  NumberOfHandlesInBlock = 255;
X
XTYPE
X  HandleBlockPtr = POINTER TO HandleBlock;
X  HandleBlock = RECORD
X                  Next: HandleBlockPtr;
X                  Contents: ARRAY[1..NumberOfHandlesInBlock]
X                            OF DynamicItem.Object;
X                END;
X
XVAR
X  FirstFreeHandle:      FreeHandle.Object;
X  CurrentHandleInBlock: ADDRESS;
X  CurrentHandlesLeft:   CARDINAL;
X  FirstBlock:           HandleBlockPtr;
X
XPROCEDURE NewHandle(): ADDRESS;
XVAR
X  NewItemHandle: DynamicItem.Object;
X  NewBlock:      HandleBlockPtr;
XBEGIN
X  IF NOT(FreeHandle.Nil(FirstFreeHandle)) THEN
X    NewItemHandle   := DynamicItem.Object(FirstFreeHandle);
X    FirstFreeHandle := FreeHandle.Next(FirstFreeHandle);
X    RETURN ADDRESS(NewItemHandle);
X  END;
X
X  IF CurrentHandlesLeft > 0 THEN
X    NewItemHandle := DynamicItem.Object(CurrentHandleInBlock);
X    CurrentHandleInBlock :=
X      ADDRESS(LONGCARD(CurrentHandleInBlock) + TSIZE(DynamicItem.Object));
X    CurrentHandlesLeft := CurrentHandlesLeft - 1;
X    RETURN ADDRESS(NewItemHandle);
X  ELSE
X    ALLOCATE(NewBlock, TSIZE(HandleBlock));
X    IF NewBlock = NIL THEN
X      RETURN NIL;
X    END;
X    NewBlock^.Next := FirstBlock;
X    FirstBlock := NewBlock;
X    NewItemHandle := DynamicItem.Object(ADR(NewBlock^.Contents));
X    CurrentHandleInBlock :=
X      ADDRESS(LONGCARD(NewItemHandle) + TSIZE(DynamicItem.Object));
X    CurrentHandlesLeft := NumberOfHandlesInBlock - 1;
X    RETURN ADDRESS(NewItemHandle);
X  END;
XEND NewHandle;
X
XPROCEDURE DisposeHandle(Item: ADDRESS);
XVAR
X  TempItem: POINTER TO FreeHandle.Object;
XBEGIN
X  TempItem  := Item;
X  TempItem^ := FirstFreeHandle;
X  FirstFreeHandle := FreeHandle.Object(Item);
XEND DisposeHandle;
X
X
XPROCEDURE DisposeAll();
XVAR
X  CurrentBlock, Temp: HandleBlockPtr;
XBEGIN
X  CurrentBlock := FirstBlock;
X  LOOP
X    IF CurrentBlock = NIL THEN
X      EXIT;
X    END;
X    Temp := CurrentBlock^.Next;
X    DEALLOCATE(CurrentBlock, TSIZE(HandleBlock));
X    CurrentBlock := Temp;
X  END;
X  FirstFreeHandle      := FreeHandle.NilObject();
X  CurrentHandleInBlock := NIL;
X  CurrentHandlesLeft   := 0;
X  FirstBlock           := NIL;
XEND DisposeAll;
X
X
XBEGIN
X  FirstFreeHandle      := FreeHandle.NilObject();
X  CurrentHandleInBlock := NIL;
X  CurrentHandlesLeft   := 0;
X  FirstBlock           := NIL;
XEND HandleCollection.
END_OF_FILE
if test 2997 -ne `wc -c <'HandleCollection.mod'`; then
    echo shar: \"'HandleCollection.mod'\" unpacked with wrong size!
fi
# end of 'HandleCollection.mod'
fi
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(5162 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XPRODUCT: Incremental Storage Manager
X
X
XVERSION: 1.0
X
X
XAUTHOR:
X     Daniel B. Hankins
X     143 Montgomery Street
X     Poughkeepsie, NY 12601
X     dan-hankins@cup.portal.com
X
X
XCREATION DATE: 1989
X
X
XRELEASE  DATE: November 21, 1989
X
X
XNOTICE OF INTELLECTUAL PROPERTY:
X     This material is *NOT COPYRIGHTED*.  By this notice, I hereby place
Xthis program and all its parts in the public domain, under the definitions
Xand restrictions of United States law.
X
X
XHISTORY OF REVISIONS:
X     None yet.
X
X
XFILE DISTRIBUTION:
X     README			FreeHandle.def
X     Build.Rexx			FreeHandle.mod
X     DynamicItem.def		HandleCollection.def
X     DynamicItem.mod		HandleCollection.mod
X     DynItem.def		Storage.def
X     DynItem.mod		Storage.mod
X     DynItemList.def		WordAlign.def
X     DynItemList.mod		WordAlign.mod
X     DynTest.mod
X
X
XWHAT IT CAN DO FOR YOU:
X
X     This set of modules constitutes a storage manager with garbage
Xcollection for Modula-2 programs.  It is written in TDI Modula-2 for the
XAmiga, but should be easily portable to other implementations and
Xarchitectures.
X     It uses *INCREMENTAL* garbage collection.  Most garbage collectors
Xcreate and destroy items willy-nilly until storage is exhausted.  Then they
Xhold up all other processing while they copy all the in-use items down to
Xone end of the storage space, thus freeing up the rest of the space for more
Xitems.
X     In incremental garbage collection, a few items are copied every time a
XNew() or Dispose() is done.  This results in overhead which in total is
Xlarger than that of stop-and-copy methods, but which never causes the
Xsystem to halt while collection is done.  This is far more suitable for
Xprograms which require real-time response or close to it.
X     Also, most storage managers begin with a statically sized storage
Xspace and allocate from that.  This requires the user to guess before
Xrunning a program that uses storage management how much storage is going to
Xbe needed.  Guess too small, and the program aborts.  Guess too large, and
Xstorage is wasted; other programs can't get space to run in.
X     This storage manager frees the user from these considerations, and is
Xa good system citizen in the bargain; it allocates storage in blocks of
X1K granularity from the operating system, and suballocates from these. 
XWhenever a block becomes unused, the manager returns it to the system.
X
X
XHOW TO USE IT:
X
X     The procedures which perform the services of the manager are defined
Xin DynamicItem.def.  Build.Rexx contains an ARexx program that will build
Xthe link and symbol files for the manager in the correct order (provided
Xyou are using TDI Modula-2).  Just import the procedures and types you want
Xfrom DynamicItem, and you'll be in business.
X     The module DynTest.mod is included for those that would like to see it
Xwork for themselves;  I used it to test the services.
X
X
XBUGS AND CAVEATS:
X
X     I've tested the code pretty thoroughly, so I don't think there are any
Xbugs in it.  If you find some, let me know via snail mail or Usenet mail. 
XThe addresses are listed at the top of the file.  Or just post in
Xcomp.sys.amiga;  I read it fairly often.
X     Performance is probably not all that great;  I organized the code in a
X*very* object oriented way, in order to make development easier on myself,
Xand to make the code easier to read for those who'd like to fiddle with it.
XAs a result, there are many procedures which consist of one, two or a very
Xfew statements.  This adds considerably to the procedure call overhead.
X
X
XPLANS AND FUTURE FEATURES:
X
X* Single-module version
X     I am in the process of developing a single-module version of this
Xprogram, with procedures made in-line where appropriate.  That version will
Xbe distributed along with the object-oriented version.  Future improvements
Xwill be made in parallel to both versions.
X
X* Granularity control
X     I plan to introduce a variable which the programmer can change to
Xindicate with what granularity storage should be allocated from the
Xoperating system.  The minimum granularity, 1K, is hard-wired into the code
Xat present.  The programmer will be able to change this to 2K or 4K or 37K
Xor whatever.
X
X* Last-ditch stop-and-copy
X     I plan to add code which handles the eventuality where no more storage
Xcan be gotten from the operating system, but not all unused space has been
Xreclaimed from existing storage blocks.  The new code will attempt to
Xrearrange items in the existing blocks in order to make room for the new
Xitem.  Currently the code checks existing blocks for unused space.  If it
Xcannot find what it needs there, then it attempts to allocate storage from
Xthe operating system.  If that fails, NIL is returned.  The new code will
Xadd another level of attempt.
X     The new feature will be able to be switched on and off by means of a
Xcontrol variable.
X
X
XTHE LAST WORD:
X
X     I hope this is of use to Modula-2 programmers.  Send comments, kudos,
Xinsults, gifts, and flames to the addresses listed at the top of this file.
XShare and Enjoy!
X
X
XTHE WORD AFTER THE LAST WORD:
X
X     "Darrell suspected someone had once again slipped him a spoon with the
Xconcave side reversed."
X     - Gary Larson, The Far Side
END_OF_FILE
if test 5162 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'Storage.def' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Storage.def'\"
else
echo shar: Extracting \"'Storage.def'\" \(1135 characters\)
sed "s/^X//" >'Storage.def' <<'END_OF_FILE'
XDEFINITION MODULE Storage;
X
X(* Product: Incremental Storage Manager
X
X   Version: 1.0
X
X   Author:
X        Daniel B. Hankins
X        143 Montgomery Street
X        Poughkeepsie, NY 12601
X        dan-hankins@cup.portal.com
X
X   Creation Date: 1989
X
X   Release  Date: November 21, 1989
X
X   Notice of Intellectual Property:
X        This material is *NOT COPYRIGHTED*.  By this notice, I hereby place
X   this program and all its parts in the public domain, under the definitions
X   and restrictions of United States law.
X
X   History of Revisions:
X        None yet.
X*)
X
XFROM SYSTEM IMPORT ADDRESS;
X
XPROCEDURE ALLOCATE(VAR addr: ADDRESS; amount: LONGCARD);
X(* allocate storage from the operating system.
X
X   addr: returns where the memory portion was allocated, word aligned.
X         returns NIL if no block of the requisite size could be found.
X   amount: the number of bytes to allocate, will be a word multiple.
X*)
X
XPROCEDURE DEALLOCATE(VAR addr: ADDRESS; amount: LONGCARD);
X(* return storage to the operating system.
X
X   addr: the portion of memory returned by ALLOCATE.
X   amount: the size of the block given to ALLOCATE.
X*)
X
XEND Storage.
END_OF_FILE
if test 1135 -ne `wc -c <'Storage.def'`; then
    echo shar: \"'Storage.def'\" unpacked with wrong size!
fi
# end of 'Storage.def'
fi
if test -f 'Storage.mod' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Storage.mod'\"
else
echo shar: Extracting \"'Storage.mod'\" \(781 characters\)
sed "s/^X//" >'Storage.mod' <<'END_OF_FILE'
XIMPLEMENTATION MODULE Storage;
X
XFROM SYSTEM IMPORT ADDRESS, NULL;
XIMPORT Memory;
X
XPROCEDURE ALLOCATE(VAR addr: ADDRESS; amount: LONGCARD);
X  (* allocate a portion of memory - return 0 if no memory available.
X
X     addr: returns where the memory portion was allocated, word aligned.
X     amount: the number of bytes to allocate, will be a word multiple. *)
XBEGIN
X  addr := Memory.AllocMem(amount, Memory.MemReqSet{Memory.MemClear});
X
X  IF addr = NULL
X  THEN
X    addr := NIL;
X  END;
XEND ALLOCATE;
X
XPROCEDURE DEALLOCATE(VAR addr: ADDRESS; amount: LONGCARD);
X  (* return a portion of memory to the heap.
X
X     addr: the portion of memory returned by ALLOCATE.
X     amount: the size of the block given to ALLOCATE. *)
XBEGIN
X  Memory.FreeMem(addr, amount);
XEND DEALLOCATE;
X
XEND Storage.
END_OF_FILE
if test 781 -ne `wc -c <'Storage.mod'`; then
    echo shar: \"'Storage.mod'\" unpacked with wrong size!
fi
# end of 'Storage.mod'
fi
if test -f 'WordAlign.def' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'WordAlign.def'\"
else
echo shar: Extracting \"'WordAlign.def'\" \(630 characters\)
sed "s/^X//" >'WordAlign.def' <<'END_OF_FILE'
XDEFINITION MODULE WordAlign;
X
X(* Product: Incremental Storage Manager
X
X   Version: 1.0
X
X   Author:
X        Daniel B. Hankins
X        143 Montgomery Street
X        Poughkeepsie, NY 12601
X        dan-hankins@cup.portal.com
X
X   Creation Date: 1989
X
X   Release  Date: November 21, 1989
X
X   Notice of Intellectual Property:
X        This material is *NOT COPYRIGHTED*.  By this notice, I hereby place
X   this program and all its parts in the public domain, under the definitions
X   and restrictions of United States law.
X
X   History of Revisions:
X        None yet.
X*)
X
XPROCEDURE WordAlign(Argument: LONGCARD): LONGCARD;
X
XEND WordAlign.
END_OF_FILE
if test 630 -ne `wc -c <'WordAlign.def'`; then
    echo shar: \"'WordAlign.def'\" unpacked with wrong size!
fi
# end of 'WordAlign.def'
fi
if test -f 'WordAlign.mod' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'WordAlign.mod'\"
else
echo shar: Extracting \"'WordAlign.mod'\" \(693 characters\)
sed "s/^X//" >'WordAlign.mod' <<'END_OF_FILE'
XIMPLEMENTATION MODULE WordAlign;
X
X(* Product: Incremental Storage Manager
X
X   Version: 1.0
X
X   Author:
X        Daniel B. Hankins
X        143 Montgomery Street
X        Poughkeepsie, NY 12601
X        dan-hankins@cup.portal.com
X
X   Creation Date: 1989
X
X   Release  Date: November 21, 1989
X
X   Notice of Intellectual Property:
X        This material is *NOT COPYRIGHTED*.  By this notice, I hereby place
X   this program and all its parts in the public domain, under the definitions
X   and restrictions of United States law.
X
X   History of Revisions:
X        None yet.
X*)
X
XPROCEDURE WordAlign(Argument: LONGCARD): LONGCARD;
XBEGIN
X  RETURN Argument + (Argument MOD 2);
XEND WordAlign;
X
XEND WordAlign.
END_OF_FILE
if test 693 -ne `wc -c <'WordAlign.mod'`; then
    echo shar: \"'WordAlign.mod'\" unpacked with wrong size!
fi
# end of 'WordAlign.mod'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have the archive.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
Mail comments to the moderator at <amiga-request@cs.odu.edu>.
Post requests for sources, and general discussion to comp.sys.amiga.