_____________________________________________________________________________

  AppEngine_Heap						 SWI &4D949
_____________________________________________________________________________

 Introduction ______________________________________________________________

AppEngine provides a sliding heap manager.  This is unlike RISC OS's own
OS_Heap heap manager in that it ensures any unused memory inside the heap is
returned to the free memory pool.

This is achieved by allowing blocks claimed from the heap to slide (move
about within the heap) and by referencing each of the blocks indirectly via a
fixed address known as an anchor.  Doing this allows the heap manager to
squeeze out any free space from the heap without this affecting the client
application.

Any heap operation can cause claimed blocks position in memory to move.

One significant difference between this heap manager and others is that it
never allows gaps of free space to appear among the blocks.  As soon as any
free space is created, then the heap manager will rearrange the heap such
that the block of free space is removed.  This means that the heap is always
kept at its smallest possible size.

 Anchors ___________________________________________________________________

Anchors are located at the base of the heap immediately before the blocks.
Initially the heap manager allocates enough space for eight anchors and hence
eight heap-managed blocks.  If you claim a ninth block, then the heap manager
will make space for eight more anchors, and so on.

The space allocated for anchors cannot be freed unless the heap is destroyed.
For this reason it is strongly recommended that you should maintain a
blocks_allocated counter in your own heap interface code, and when it
becomes zero, you should delete the heap.  When a claim for a block is made
and blocks_allocated is zero, you should (re-)create the heap.

 Warnings __________________________________________________________________

i.	When the heap manager is active and is residing at the top of your
	application's slot, you should *never* use Wimp_SlotSize (or END= in
	BASIC since that calls Wimp_SlotSize).  Neither should you attempt to
	store anything above the heap.

ii.	Executable code may not be contained in dynamic areas, so you should
	avoid keeping code in a heap-managed block.

iii.	The internal structure of the heap will not be documented here.  To
	ensure future compatibility you should only use the defined software
	interfaces.

 Notes _____________________________________________________________________

i.	The heap manager is very frugal, it doesnt align blocks or block
	sizes to 16-byte boundaries as some others do.

ii.	It is written in 100% hand-crafted assembler and I've optimised
	certain parts of it for the StrongARM, despite not owning one. (In
	fact it was written [and I'm writing this] on my 2Mb ARM 2 A3000. :-)

iii.	It is coded to work if using memory above 2Gb, which I understand
	will happen if you have 128Mb or more memory (this remains untested).

 Example ___________________________________________________________________

REM Create a heap residing above BASIC's workspace
SYS "AppEngine_Heap",0,HIMEM,"" TO ,heap%

REM Claim a 2000 byte block
SYS "AppEngine_Heap",2,heap%,2000 TO ,anchor%

REM Find the base address of the block
address%=!anchor%

REM Add 48 bytes to the end of the block
SYS "AppEngine_Heap",4,heap%,anchor%,48 TO ,success%

REM Delete the block
SYS "AppEngine_Heap",3,heap%,anchor% TO ,anchor%

REM Delete the heap
SYS "AppEngine_Heap",1,heap% TO ,heap%
_____________________________________________________________________________

							       AppEngine_Heap
								 (SWI &4D949)

	Provides a sliding heap manager

On entry
	R0 = reason code
	other registers are reason code dependent

On exit
	R0 preserved
	other registers are reason code dependent

Interrupts
	Interrupt status is undefined
	Fast interrupts are enabled

Processor mode
	Processor is in SVC mode

Re-entrancy
	Not defined

Use
	The action of the SWI depends on the reason code passed in R0:

		R0	Action
		0	creates a new heap
		1	deletes a heap
		2	claims a block of memory from a heap
		3	releases a block of memory from a heap
		4	resizes a block of memory in a heap

Related SWIs
	OS_Heap, AppEngine_MemoryOp 0

Related vectors
	None

_____________________________________________________________________________

							     AppEngine_Heap 0
								 (SWI &4D949)

	Creates a new heap

On entry
	R0 = 0
	R1 = pointer to address to create heap at (usually =HIMEM),
	     or zero to create a dynamic area for the heap
	R2 = pointer to a name for the dynamic area (if R1=0)

On exit
	R1 = pointer to heap

Use
	This call is used to create a new heap, either at the end of
	application memory or in a new dynamic area.

	The heap manager will automatically claim the required amount of
	memory from the free pool to set up the heap structure.
_____________________________________________________________________________

							     AppEngine_Heap 1
								 (SWI &4D949)

	Deletes a heap

On entry
	R0 = 1
	R1 = pointer to heap

On exit
	R1 = 0 (i.e. heap to return)

Use
	This call is used to delete the specified heap.  All memory
	associated with the heap is returned to the free pool.
_____________________________________________________________________________

							     AppEngine_Heap 2
								 (SWI &4D949)

	Claims a block of memory from a heap

On entry
	R0 = 2
	R1 = pointer to heap
	R2 = size of block required (bytes)

On exit
	R1 = pointer to anchor

Use
	This call is used to claim a block of memory from the heap.

	The size of the block claimed will always be rounded up to at least
	the nearest multiple of four bytes.

	The call returns a pointer to a word holding the address of the
	block, so in BASIC terms block_address%=!anchor%.  Blocks can move
	about in response to *any* heap operation, so you must ensure your
	block_address% is updated after any heap operation.
_____________________________________________________________________________

							     AppEngine_Heap 3
								 (SWI &4D949)

	Releases a block of memory from a heap

On entry
	R0 = 3
	R1 = pointer to heap
	R2 = pointer to anchor

On exit
	R1 = 0 (i.e. anchor to return)

Use
	This call is used to release a block of memory from the heap, and
	return the resultant free memory back to the free pool.
_____________________________________________________________________________

							     AppEngine_Heap 4
								 (SWI &4D949)

	Resizes a block of memory in a heap

On entry
	R0 = 4
	R1 = pointer to heap
	R2 = pointer to anchor
	R3 = number of bytes to be added or removed from the end of the
	     specified block (a signed integer)

On exit
	R1 = -1 for success, 0 for failure

Use
	This call is used to add (R3 positive) or remove (R3 negative) memory
	to/from the end of the specified block.

	If adding to a block, then on return R1 holds a value indicating
	whether the operation was successful or not.

	If removing from a block, then the resultant free memory is returned
	back to the free pool.

	Note that as with the claim operation, block sizes are rounded *up*
	to at least the nearest multiple of four bytes.  This means that if
	you try to remove, say, -3 bytes from a block then *nothing* will
	actually be removed since -3 is rounded up to zero.
