ML Reference
MLMemoryManager Overview


Contents

Classes

MLMemoryAllocator
MLMemoryBlockHandle
MLMemoryManager
MLWeakMemoryBlockHandle

Introduction

The memory manager is the library to manage memory blocks of significant sizes, which are allocated by different libraries, e.g. the ML, the GVR. This makes it possible to keep the accumulated size of the cached memory block accross all libraries in an application below a certain limit. This reduces the slow process of swapping memory to disk.

Overview

The memory manager can allocate memory blocks of random size, but it does not return the memory block to the user. Instead it returns a strong handle for the memory block, which grants access to the data pointer of the memory block. The memory block size adds to the size of locked memory, which is tracked by the memory manager. After the data has been used, the memory handle may be turned into a weak handle. This appends the memory block to the cache list of the memory manager (provided that no other strong handle for the memory block exists). The locked memory size is decreased and the cache size increased.

If neither weak handles nor strong handles reference a memory block, then it is deleted immediately. To access a cached memory block again, the weak handle is simply assigned to a strong handle. This causes the removal of the memory block from the cache list automatically.

If the accumulated sizes of the memory blocks in the cache list exceed the "cache and locked memory size limit", then memory blocks are removed from the cache list and deleted, according to the least-recently-used principle.

The image below shows that the cache list contains only those memory blocks that are exclusively referenced by weak handles. The memory blocks, which exist outside the cache list, are always referenced by at least one strong handle and may also be referenced by weak handles.

Relations between cache list, locked memory, memory blocks and handles

Thread Safety

The memory manager can be thread safely used, more precise the caching of the memory manager is thread safe. The thread safe operations include assignment of strong and weak handles, memory allocation and adding allocated memory.
All thread safe methods are listed in Thread-safe Classes and Functions.

Code Examples

Allocating a memory block

The strong handle of a MLMemoryBlock.
static MLMemoryManager * singleton()
The singleton is the only way to communicate with the memory manager.
MLMemoryBlockHandle allocate(unsigned int id, size_t size)
Allocates a memory block with the given size in bytes.


Accessing the data of a memory block

// ...
int* data = static_cast<int*>(handle.data());
for (size_t i=0; i<handle.size(); ++i) {
int readValue = data[i];
data[i] = readValue+1;
}
size_t size() const
Returns the size of the data. If this handle is null, then 0 is returned.
void * data() const
Returns the data of the memory block. If this handle is null, then NULL is returned.


Releasing a memory block

{
// ...
// Assign the handle to the weak handle to release it,
// i.e. the memory block is appended to the cache list.
weakHandle = handle;
}
// Now only the weak memory handle exists
The weak handle of a MLMemoryBlock.


Reusing a memory block

// ...
MLMemoryBlockHandle handle = weakHandle;
if (!handle.isNull()) {
// The data still exists and can be used
} else {
// The data was deleted while it was cached, so allocate a new memory block
handle = MLMemoryManager::singleton()->allocate(id, size);
}
bool isNull() const
Returns true if the handle does not reference a valid memory block.


Adding already allocated memory

void deleteMemoryCallBack(void* data, size_t sizeIsNotUsed, void* userDataIsNotUsed)
{
delete [] static_cast<MyCustomObject*>(data);
}
int main(int argc, char** argv)
{
// ...
MyCustomObject* data = new MyCustomObject[1000];
MLMemoryManager::singleton()->addAllocatedMemory(id, data, size, deleteMemoryCallBack, NULL);
// ...
}
MLMemoryBlockHandle addAllocatedMemory(unsigned int id, void *data, size_t size, MLDeleteMemoryBlockCallback deleteMemoryBlockCallback, void *deleteMemoryBlockCallbackUserData)
Adds a pre-allocated memory block of the given size in bytes, which is later deleted by the given cal...


Initializing and deinitializing the memory manager

// ...
static void deinitialize()
Deinitializes the memory manager.
static void initialize()
Initializes the memory manager with a default limit of one gigabyte for the joint size of the cache a...


Setting the cache and locked memory size limit

void setCacheAndLockedMemorySizeLimit(const size_t cacheSizeLimit)
The memory manager deletes memory blocks in the cache list automatically if the cache and locked memo...