/srcheap.txt
\                                                                    vandys
\ heap.f
\       Heap allocator wordset
\
\ A very simple first-fit algorithm.  Coalescing is only done when
\ explicitly requested.  This permits allocation and free to be very
\ simple and very fast, but assumes that there will be points in time
\ where CPU time may be spent scanning the potentially fragmented
\ free list and reassembling contiguous runs of memory.  Pay me now
\ or pay me later.
\
\ The first two words of each memory block on the free list are
\  formatted as a size field, followed by a next pointer.  To
\  permit compatibility with the allocated format, the size field
\  value does not include the "size" field itself, but does include
\  the "next" field.
\ Allocated blocks are seen as the memory pointer by the application;
\  at cell- is a word recording the size of the allocated block,
\  which does not include this "size" word.
\
\ No memory is initially available to the heap.  A simple initialization
\ might be: here 65536 add-memory 65536 allot



\                                                                    vandys
extensions definitions

variable heap	\ Free blocks hang here
4 cells constant MINALLOC

\ Contribute memory to the free pool
: add-memory ( a u -- )
    cell- over ! heap @ over cell+ ! heap !
;

\ Tell size of largest allocation which would succeed
: available ( -- u )
    0 heap @ begin ?dup while
	dup @ rot max swap
    cell+ @ repeat
;








\                                                                    vandys
\ Split memory segment if appropriate, consuming requestor's size value.
\ Returned pointer is always the original one, but its "next" field
\ may have been adjusted to point to a newly created segment split
\ off from the original chunk.
: (split)	( ptr u -- ptr )
    \ If only one would fit, use it all
    2dup 2* swap @ > if drop exit then
    \ Calculate new chunk addr, assign it remainder of space
    2dup + >r over @ over - r@ !
    \ Copy old next pointer into place
    over cell+ @ r@ cell+ !
    \ Point next pointer at this new chunk
    over cell+ r> swap !
    \ Adjust size to be just the requested amount
    over !
;








\                                                                    vandys
\ Allocate memory
: allocate ( u -- a 0 | ior )
    aligned MINALLOC max			\ At least this much
    heap begin dup @ ?dup while			\ u &ptr ptr
	rot >r dup @				\ &ptr ptr size | r: u
	r@ >= r> swap if			\ &ptr ptr u
	    (split)				\ &ptr ptr
	    cell+ tuck @ swap !			\ ptr
	    0 exit
	then
	rot drop swap				\ u ptr
    cell+ repeat 2drop -1			\ ior == failure
;

\ Free memory
: free ( a -- 0 | ior )
    cell- heap @ over cell+ ! heap !
;






\                                                                    vandys
\ Resize existing memory block
: resize ( a1 u -- a1 ior | a2 0 )
    aligned MINALLOC max			\ At least this much
    allocate ?dup if exit then
    2dup over cell- @ cmove swap free drop 0
;

\ Display state of heap
: .heap ( -- )
    base @ hex
    heap @ begin ?dup while
	    ." [" dup 1 u.r ." : " dup @ 1 u.r ." ]" cell+ @
    repeat
    base !
;

\ TBD--an on-demand coalescer

only