About the Mem sublibrary
========================

"Flex" is the RISC OS Lib 'flexible' malloc for desktop tasks
"Mem" is DeskLib's equivalent thereof, and uses an interface that is
very similar to that of flex.

Mem memory chunks are held in a 'heap' of memory above the area grabbed
by the SharedCLibrary for mallocs and stackspace, extending up to the
end of the WimpSlot, which is adjusted up & down as necessary.

The major feature that externally distinguishes Mem from flex() is that
the heap is NOT compacted automatically (flex keeps the entire heap
compacted at all times). This has several advantages:
  - You can rely on pointers remaining constant at all times between
    calls to Mem_Compact() (and other Mem_ calls if you allow it)
  - everything is a lot faster if you are allocating and/or
    deallocating many chunks in one go.

The idea behind this is that you simply call Mem_Compact before
calling Wimp_Poll - this returns free memory to the Wimp as effectively
as the flex system did, but saves us from having to waste time on
multiple compactions between Wimp_Polls.

Automatic compaction (a la flex) can be turned on (or off) at any time
so the Mem system can be made to emulate flex_ if you really want it.


Important Notes
===============

* The Mem sublibrary has not been thoroughly tested yet, so don't be too
  surprised if it suddenly dies on you... However, it seems to work OK for
  the tests I have had time to perform on it.

* For reasons utterly unknown to me, Mem_MidExtend (and possibly others, like
  Mem_Compact, for example) will fail if your initial WimpSlot is a bit tight.

  (If you allocate a large enough WimpSlot, malloc and stack extension will
  fail with a 'not enough memory' error when they run out. However, with a very
  tight WimpSlot, I got all kinds of neat errors which appeared to be because
  of a corrupt stack, which usually killed things on exit from MidExtend!

  The problem went away when I made the main program slightly smaller, so
  it might only occur in very special circumstances. However, if your program
  dies with calls to non code and other such stuff, try increasing the WimpSlot
  in your !Run file...
  
  If anyone can tell me WHY this was happening, I'd love to know!


Possible mem improvements in the future
=======================================

No guarantees, but here's my list of ideas which somebody (you perhaps?)
may be interested in implementing for future releases of DeskLib.

* Add the missing code from mem_MidExtend which will improve the chances
  of extending large blocks in low memory situations.

  This may be done by adding another mem extend call (mem_ForceExtend)
  which will compact the heap and then force extension of the block by
  moving everything after the chunk up to make space (if possible). This will
  allow you to extend chunks whenever possible, but still elect to link in
  the extra code for these situations if you really need it.

* Add the ability to lock mem chunks (preferably after being moved to the
  'safest' address possible, to minimise memory trapping) to stop them ever
  moving. Ability to unlock (and move) these chunks when you feel like it.

* Add function to emulate flex_budge, which will allow malloc and
  stack extension attempts to shift the mem heap up if needed. (Not
  recommended, as this means you must be VERY careful with anchors)
  Note that although this code exists (in the form of ShiftHeap), it
  must be repeated within the budge function, as you are in the process of
  finding more memory for the stack, so can't call other functions ;-(

* Possibly a flex_budge style function which will allocate a new chunk
  and LOCK it, and give this memory to the SharedCLibrary, so that malloc
  and stack extension will "never" fail.

* Additional code for mem_Alloc to provide different allocation strategies.
  Currently, a 'best fit' is found, but it is faster to find the 'first fit',
  especially if you are working with a lot of small, similar-sized chunks.

  Another allocation strategy which might even be better than either of these
  is 'grab' - always allocate the chunk at the end of the heap, and rely on
  the user calling Compact enough to keep the free space at the end of the heap
  (where the Wimp Pool is thought of as 'memory at the end of the heap')
  This is the fastest strategy, and also needs the minimum of code.
  (If you wish to try this out, just delete the first half of the code in
  mem_Alloc, and use 'bestfit' == lastchunk!)

* Addition of a flagword to each mem chunk. Uses I can see for this are:
  - Chunks which have their own 'mem_autocompact' style values (i.e. some
    chunks are allowed to move, others should move only if necessary, and
    others are not allowed to move ever).

  - Chunks which never release memory when you MidExtend them (i.e. they will
    grow, but will never shrink. This is a very good idea if you have a data
    structure which gets bigger and smaller all the time, but never goes above
    a (reasonable) maximum - instead of it causing endless heap relocations,
    mem can just keep the memory around on the assumption that the data in
    the chunk will expand again in the near future.

  - Data pertaining to the use of mem anchors from within a mem chunk. As
    mem minimises the amount of shifting of chunks, it is more possible to
    resolve chunk-to-chunk references as chunks are shifted. This would be
    slower (especially if used a lot), but would be extremely convenient, as
    it would allow things like trees and linked lists to be constructed
    easily across a set of mem chunks...
    Or perhaps just a way of indirecting dereferences through mem, which can
    look up the current address of the chunk for you -slow to search through
    such structures, but a useful ability.

  - Addition of a 'moved' flag. This can be set whenever mem moves a chunk,
    and the user can check this flag at important points to see if they need
    to bother updating pointers into the chunk - after such adjustment, the
    flag is cleared again.
