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.