home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Datafile PD-CD 5
/
DATAFILE_PDCD5.iso
/
utilities
/
e
/
exthelp
/
!Ext
/
Heap
< prev
next >
Wrap
Text File
|
1993-04-12
|
12KB
|
402 lines
Heap memory manager
===================
WimpExtension's heap manager is one of the module's most powerful, useful,
and - unavoidably - complicated features. This document is provided to
explain more about what a relocatable heap is, and how to use it.
Programming examples in this document are given in BASIC, because practically
everyone knows how to use it.
This document assumes that you know how to program in the RISC OS Wimp, and
that you understand terms such as "WimpSlot" (read the chapter "The Window
Manager" in the PRMs if you don't).
Read the "SWIs" and "Manual" files for a brief description of the parameters
for the SWI WimpExt_Heap.
Why do I need a heap?
---------------------
Any program which uses more than one block of memory which changes size needs
a heap manager. For example, Edit and Paint need a heap manager, because they
can have several files loaded at once, all of which can be changing size at
any time. The files are loaded into memory "blocks", which are provided by
the heap manager.
Why use a relocatable heap?
---------------------------
RISC OS provides a non-relocatable heap manager. This means that the memory
blocks are fixed in memory, and don't move about. The problem with this is
that it gets very wasteful on memory when you have finished using the block.
Say you loaded three files into a text editor:
/--------\ Highest memory address
| File 3 |
| |
|--------|
| File 2 |
| |
| |
|--------|
| File 1 |
\--------/ Lowest memory address
This is fine, no problems so far. However, suppose the user decided the close
the file "File 2":
/--------\ Highest memory address
| File 3 |
| |
|--------|
| unused |
| |
| |
|--------|
| File 1 |
\--------/ Lowest memory address
The block of memory in the middle is now unused, and is wasting space. A
non-relocatable heap manager can't do anything about this. Another example is
if the user adds something to File 2, making it longer. File 2 will no longer
fit in its original block - if you extended it then it would overwrite
File 3. Therefore the heap manager has to copy the whole file up in memory,
as shown in the diagram:
/--------\ Highest memory address
| File 2 |
| |
| |
| |
|--------|
| File 3 |
| |
|--------|
| unused |
| |
| |
|--------|
| File 1 |
\--------/ Lowest memory address
WimpExtension provides a relocatable heap manager, however. This means that
the heap manager is allowed to move the blocks about, to try and reduce the
amount of wasted memory. In the situation above, for example, WimpExtension
would move File 2 and File 3 down in memory, like so:
/--------\ Highest memory address
| File 2 |
| |
| |
| |
|--------|
| File 3 |
| |
|--------|
| File 1 |
\--------/ Lowest memory address
As you can see, this can save a lot of memory.
Anchors
-------
The only disadvantage of a reloctable heap is due to the fact that it IS
relocatable - the blocks of memory aren't fixed and may move about. A
question which immediately arises is "How do I find my memory block?" - if
the block may have moved, how do you find it?
The answer is by using an "anchor". An anchor is a word in memory. The
contents of this word is always a pointer to the start of the block. ie:
/-------\
| |
/--------\ | |
| anchor |--------->| block |
\--------/ \-------/
The anchor always stays fixed in the same place in memory, so you always know
where to find it. So, to find the location of your block, you would use:
block%=!anchor% : REM block% now points to the first byte in the block
The anchors are stored all together at the beginning of the heap.
Size of blocks
--------------
The word before the start of any block contains the size of the block in
bytes. So to find the size of a block, you would use:
size%=!(block%-4)
or:
size%=!( (!anchor%) -4)
(because block%=!anchor%).
Due to the way the heap manager works, the size of a block is always four
plus a multiple of eight (ie. 12, 20, 28, etc.). If you ask WimpExtension to
make a block with a size which isn't four plus a multiple of eight, then the
size will be rounded up by between one and seven bytes, to take it to the
next largest acceptable size.
Initialising the heap
---------------------
Before you can use any of the heap operations, you must initialise the heap.
This requires two parameters - the number of anchors to create initially, and
the address in memory of the base of the heap.
The anchors are stored all together at the beginning of the heap. Because you
need one anchor for every block in use, the number of anchors is effectively
the maximum number of blocks you can have in use at any one time. You can
create more anchors later, but it is best to create enough now, and then you
don't have to worry about it later. Remember that anchors do take memory
though, so don't go wild.
For example:
SYS "WimpExt_Heap",0,base%,anchors%
Note that a heap which is empty (ie. no blocks are in use) takes absolutely
no memory at all.
Allocating blocks
-----------------
Whenever you ask WimpExtension to make you a new block (called "allocating" a
block), it gives you a pointer to the anchor for that block. You must store
the pointer to the anchor, NOT the pointer to the block, because the anchor
will never move, but the block may do. For example, to ask WimpExtension for
a block "size%" bytes long, you would use:
SYS "WimpExt_Heap",2,,size% TO ,anchor%
If WimpExtension cannot create the block, because there is not enough free
memory, then the anchor returned will be zero. You need to check for this
before writing anything into the block. eg:
SYS "WimpExt_Heap",2,,size% TO ,anchor%
IF anchor%=0 THEN ERROR 1,"Not enough free memory"
Freeing blocks
--------------
When you have finished using a block, you use the "Free block" call to tell
WimpExtension that you don't need the block any more, and the memory it takes
up can be re-used. eg:
SYS "WimpExt_Heap",3,anchor%
or:
SYS "WimpExt_Heap",3,block%
The block will be added to WimpExtension's list of free blocks.
Reallocating blocks
-------------------
Sometimes you will want to re-size a block - this is called "reallocating"
the block. WimpExtension allows you to increase or decrease the size of any
block at any time. eg:
SYS "WimpExt_Heap",4,block%,new_size% TO ,flag%
or:
SYS "WimpExt_Heap",4,anchor%,new_size% TO ,flag%
If the flag is zero on exit then the re-size failed because there wasn't
enough free memory.
Note that this call may cause the specified block to move in memory. Only the
specific block that you are re-sizing can move, though - all the other blocks
will stay where they are.
Garbarge collection
-------------------
"Garbage collection" is the whole point of the relocatable heap. This is the
process of shuffling the blocks about in memory, so that no memory is wasted.
For example, if the heap was in the following state:
/---------\ Highest memory address
| block 2 |
| |
|---------|
| free |
| |
| |
|---------|
| block 1 |
\---------/ Lowest memory address
then performing garbage collection would shuffle the blocks as follows:
/---------\ Highest memory address
| block 2 |
| |
|---------|
| block 1 |
\---------/ Lowest memory address
This then allows WimpExtension to decrease your task's WimpSlot, thus making
this memory available to any other programs which might need it.
Two garbage collection calls are provided; the Tidy call:
SYS "WimpExt_Heap",5
and the Compact call:
SYS "WimpExt_Heap",6
The Tidy call just tidies the heap a little bit - the heap won't necessarily
immediately be shuffled into the ideal position, but the call is usually
quite fast. This call is intended to be called just before you call
Wimp_Poll. If you set bit 3 of R2 when you called WimpExt_Initialise, then
the heap will be automatically Tidied once a second, in WimpExt_PrePoll. Most