/** @page mem Memory Management @section mem_overview Overview A memory manager is an instance of a structure type #qse_mmgr_t. Creating and/or initializing an object requires a memory manager to be passed in. The default memory manager is merely a wrapper to memory allocation functions provided by underlying operating systems: HeapAlloc/HeapReAlloc/HeapFree on _WIN32 and malloc/realloc/free on other platforms. You can get this default memory manager with qse_getdflmmgr() and can change it with qse_setdflmmgr(). Typically, the name of a function creating an object begins with @b qse_, ends with @b _open, and accepts a memory manager as the first parameter. See qse_mbs_open() for instance. So you can customize memory management at the per-object level. Three types of special memory allocators are provided in the library. - #qse_xma_t - generaic private heap allocator - #qse_fma_t - fixed-size block allocator - #qse_pma_t - pool-based block allocator @section mem_xma Priviate Heap While the default memory manager allocates memory from a system-wide heap, you can create a private heap and use it when you create an object. The #qse_xma_t type defines a private heap manager and its functions offer sufficient interface to form a memory manager over a private heap. A typical usage is shown below: @code qse_mmgr_t mmgr; // Create a private heap using the default memory manager heap = qse_xma_open (QSE_NULL, 0, 1024 * 1024); // 1M heap // Initialize a memory manager with the heap mmgr.alloc = (qse_mmgr_alloc_t)qse_xma_alloc; mmgr.realloc = (qse_mmgr_realloc_t)qse_xma_realloc; mmgr.free = (qse_mmgr_free_t)qse_xma_realloc; mmgr.ctx = heap; // You can pass 'mmgr' when you create/initialize a different object. .... .... // Destroy the private heap qse_xma_close (heap); @endcode Note that creating a private heap requires a memory manager, too. The example above used the default memory manager to create a private heap within the global heap. This means that you can split a heap to smaller subheaps. @section mem_fma Fixed-size Block Allocator If memory blocks to allocate share the same size, you can use #qse_fma_t for performance. It achieves fast memory allocation as it knows the block size in advance. The blocks allocated with this memory allocator don't outlive the memory allocator itself. That is, qse_fma_close() or qse_fma_fini() invalidates all the pointers allocated with qse_fma_alloc(). @code qse_fma_t* fma; int* ptr; fma = qse_fma_open (QSE_NULL, 0, sizeof(int), 10, 0); // create an allocator ptr = (int*)qse_fma_alloc (fma, sizeof(int)); // allocate a block *ptr = 20; // access the block qse_fma_free (fma, ptr); // free the block qse_fma_close (fma); // destroy the allocator @endcode @section mem_pma Simple Memory Pool Allocator If you want to allocate blocks quickly but don't want to resize or deallocate the blocks individually, you can use #qse_pma_t. @code qse_pma_t* pma; int* ptr; pma = qse_pma_open (QSE_NULL, 0); // create an allocator ptr = (int*)qse_pma_alloc (pma, sizeof(int)); // allocate a block *ptr = 20; // access the block qse_pma_close (pma); // destroy the allocator @endcode */