home *** CD-ROM | disk | FTP | other *** search
Modula Definition | 1990-05-02 | 5.7 KB | 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.
-