DeskLib 2.90a:Mem.h


Contents


Introduction and Overview

Mem provides a 'heap' of memory above the area set up by the Shared C Library for mallocs and stackspace, extending up to the end of the Wimpslot which is adjusted up and down as necessary.

The system works with "anchors" - pointers to memory blocks in the heap which can be updated automatically by Mem when the blocks are rearranged. The allows Mem to compact the heap or rearrange the blocks in order to waste the least space.

You can choose to let Mem rearrange the blocks whenever it wants, only when it needs to or only when you explicitly request that the heap be compacted. You choose this by setting the value of mem_autocompact, so you can change the behaviour in different parts of the program depending on how the situation can best be managed.

The idea is that you call Mem_Compact before calling Wimp_Poll, which should ensure that the heap has little wasted space, but doesn't waste time by compacting after every single operation. This leads to quicker allocation and deallocation of chunks.

Note that by default, Mem will only autocompact if it has no choice, but *may* autocompact during any Mem_ call. Avoid pointer arithmetic unless mem_autocompact is set to mem_NOCOMPACT.


Functions


Mem_Initialise

BOOL Mem_Initialise(void );

Initialises the Mem system ready for use.

Note that this locks down the malloc and stack memory area to the current WimpSlot size at the point of calling, and builds a Mem heap above this. Malloc and stack allocation will not be able to get more memory than is originally available in your WimpSlot, so get it right!


Mem_Alloc

BOOL Mem_Alloc(mem_anchor *anchor, int numbytes);

This attempts to allocate the given amount of memory to the anchor pointed to by 'anchor'. This updates the anchor to point to the allocated block, or NULL if it fails to allocate the memory. The returned block is word-aligned.

It returns TRUE if successful, FALSE otherwise.


Mem_MidExtend

BOOL Mem_MidExtend(mem_anchor *anchor, int at, int by);

This function attempts to alter the size of an existing Mem block, by inserting a block of 'by' bytes at offset 'at' within the block. If 'by' is negative then the -by bytes below 'at' will be deleted. Either way, existing data (except that deleted) is preserved.


Mem_MoveAnchor

void Mem_MoveAnchor(mem_anchor *from, mem_anchor *to);

This function copies moves an anchor from one variable to another. This is necessary because, due to the relocating nature of Mem chunks, anchors are automatically updated. If you simply copy the value, the new anchor will not be updated, and the place where the old anchor was stored will instead by overwritten.

If this function works, the anchor pointed to by 'from' will contain NULL, and the anchor pointed to by 'to' will contain the previous contents of 'from'. Otherwise, 'to' will contain NULL and 'from' will be left alone.


Mem_Free

void Mem_Free(mem_anchor *anchor);

This releases the given block of memory back to the free pool. The anchor's contents will be set to NULL.


Mem_Compact

void Mem_Compact(void );

This compacts the Mem heap, moving free space to the end and releasing what it can back to the Wimp. This is likely to move some Mem chunks around if there is any free space in the heap at all. You can't rely on anchors being constant across calls to this function.

Ideally, call this just before calling Wimp_Poll so that the Wimp has access to as much memory as possible, and to keep the heap tidy.

If mem_autocompact is not set to mem_NOCOMPACT, any other Mem function could also call this one.


Mem_Size

int Mem_Size(mem_anchor *anchor);

This returns the current size (in bytes) of the given Mem chunk.


Mem_CheckHeap

BOOL Mem_CheckHeap(void );

This checks the state of the Heap to ensure that all links are intact and internally consistent. It raises an error with Error_Report for the first problem it finds, and returns FALSE. If the heap is intact, it returns TRUE.

Useful when debugging to see if you've accidentally written over part of the Mem heap.


Types


mem_anchor

typedef void *mem_anchor;

The Mem functions accept a pointer to a mem_anchor to allocate, seallocate, or generally do anything with memory in the heap. You pass a pointer to your anchor to the various Mem routines so that they can alter the contents of the anchor whenever necessary.


mem_compaction

typedef enum
{
mem_NOCOMPACT = 0,
mem_FASTCOMPACT = 1,
mem_PARTCOMPACT = 1,
mem_FULLCOMPACT = 2
} mem_compaction;

These are the different options for the auto-compacting of the Mem heap, which is controlled by mem_autocompact.


Variable


mem_autocompact

extern int mem_autocompact;

This variable controls when Mem is allowed (or required) to compact the heap. If you set it to mem_NOCOMPACT, it will never move any of the blocks around except when you call Mem_Compact. mem_PARTCOMPACT means that it is only compacted when it might free enough space to allocate a block, or when you call Mem_Compact. This is the default setting. mem_FULLCOMPACT means that whenever you do a Mem operation, the heap is compacted. This offers no real advantage over the other options , and so is not recommended.

You can change the value at any time and the change will take immediate effect. If you want to be able to rely on pointers not changing during a single function, simply set mem_autocompact to mem_NOCOMPACT at the start and back to mem_PARTCOMPACT at the end.