home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
375.lha
/
IncrStorageManager_v1.0
/
DynamicItem.def
< prev
next >
Wrap
Text File
|
1990-05-02
|
6KB
|
157 lines
DEFINITION MODULE DynamicItem;
(* Product: Incremental Storage Manager
Version: 1.0
Author:
Daniel B. Hankins
143 Montgomery Street
Poughkeepsie, NY 12601
dan-hankins@cup.portal.com
Creation Date: 1989
Release Date: November 21, 1989
Notice of Intellectual Property:
This material is *NOT COPYRIGHTED*. By this notice, I hereby place
this program and all its parts in the public domain, under the definitions
and restrictions of United States law.
History of Revisions:
None yet.
*)
FROM SYSTEM IMPORT ADDRESS;
TYPE
Object;
InitProc = PROCEDURE(ADDRESS);
TermProc = InitProc;
PROCEDURE New(Size: LONGCARD; InitIt: InitProc; TermIt: TermProc): Object;
(* Size: *in* Size in bytes of chunk to be allocated
InitIt: *in* The procedure which will initialize the contents of the
chunk. It is passed the address of the first byte of the
chunk.
TermIt: *in* The procedure which will clean up the contents of the
chunk when its storage is reclaimed. For instance, if
the chunk contains variables of type DynamicItem.Object,
TermIt should DynamicItem.Dispose each of them so that
their reference counts can be accurately maintained.
*out* The resulting object
*)
PROCEDURE Ref(Item: Object): Object;
(* Item: *in* The chunk to which another reference is to be generated.
*out* The chunk after its reference count is incremented.
Explanations and Recommendations:
Although the Modula-2 compiler will allow the programmer to perform
assignment between variables of type DynamicItem.Object, she should not.
This storage manager relies on a technique called reference counts. The
reference count (which is embedded in the header of a storage chunk) is
intended to reflect the number of variables (pointers, actually) which
are accessing the same chunk. The reason for this is so that the
storage manager will know when it can remove the chunk from the active
list and reclaim the storage it consumed.
So if variables A, B, and C are all of type DynamicItem.Object, and
all reference the same storage chunk, then the reference count of the
chunk should be three.
To make two variables refer to the same object, use the following:
A := DynamicItem.Ref(B);
instead of
A := B;
If you want to copy the contents of an chunk A into another chunk
B, then the programmer should create a new dynamic item object B, access
the contents of both, and then copy the contents. For instance:
B := DynamicItem.New(ASize, AInit, ATerm);
ACopy(DynamicItem.Access(A), DynamicItem.Access(B));
where ACopy takes a pair of pointers to the kind of chunk being copied.
*)
PROCEDURE Dispose(Item: Object);
(* Item: *in* The chunk to be disposed of.
Explanations and Recommendations:
Dispose does *not* necessarily reclaim the storage used by a chunk.
Dispose decrements the reference count of the chunk (see procedure Ref,
above); there is now one less pointer to the chunk. Only when there are
no pointers left to a chunk (i.e. reference count = 0) does Dispose
actually attempt to reclaim the storage used by the chunk. Just
before reclaiming that storage, it runs the TermIt procedure (see
procedure New, above) stored in the header of the chunk against the
contents of that chunk. The TermIt procedure is meant to be used for
Dispose-ing of any chunks the chunk may reference.
For instance, suppose that the chunk the programmer is working
with is a record which has three variables of type DynamicItem.Object.
TermIt should DynamicItem.Dispose each of the three variables.
Otherwise, the three chunks referenced will *never* be reclaimed;
their reference counts will never go to zero, and they will become
unusable dead storage.
*)
PROCEDURE Access(Item: Object): ADDRESS;
(* Item: *in* The chunk which is to be accessed.
*out* The address of the contents of the chunk.
Explanations and Recommendations:
Whenever DynamicItem.New or DynamicItem.Dispose is called,
the contents of a chunk may move in memory. So it is a good idea to
avoid code like this:
ChunkPtr := DynamicItem.Access(ChunkVar);
...
(* other code *)
...
DynamicItem.Dispose(ChunkVar2);
ChunkPtr^.XValue := 10;
because ChunkPtr may no longer be pointing at the contents of the
chunk after a New or Dispose is done. A better practice is to
*always* Access a chunk *just before* its contents are to be
manipulated, like this:
ChunkPtr := DynamicItem.Access(ChunkVar);
...
(* other code *)
...
DynamicItem.Dispose(ChunkVar2);
>>> ChunkPtr := DynamicItem.Access(ChunkVar);
ChunkPtr^.XValue := 10;
*)
PROCEDURE Set(Item:Object; NewDynItem: ADDRESS);
(* DO NOT USE THIS PROCEDURE; IT IS FOR THE EXCLUSIVE USE OF OTHER PARTS
OF THE STORAGE MANAGER!
*)
PROCEDURE DisposeAll();
(* This procedure returns *all* storage allocated by the storage manager
to the operating system. It is a good idea to call this procedure
just before exiting your program; it makes sure you haven't forgotten
to return any resources you've used.
*)
PROCEDURE NilObject(): Object;
(* This procedure returns an uninitialized chunk, which cannot be used
except for testing to see if another chunk is uninitialized. It is
primarily for use of other storage manager procedures.
*)
PROCEDURE Nil(Item: Object): BOOLEAN;
(* This procedure returns TRUE if a chunk is uninitialized, FALSE
otherwise.
*)
END DynamicItem.