244 lines
7.4 KiB
C
244 lines
7.4 KiB
C
|
/*
|
||
|
* $Id$
|
||
|
*
|
||
|
Copyright (c) 2016-2018 Chung, Hyung-Hwan. All rights reserved.
|
||
|
|
||
|
Redistribution and use in source and binary forms, with or without
|
||
|
modification, are permitted provided that the following conditions
|
||
|
are met:
|
||
|
1. Redistributions of source code must retain the above copyright
|
||
|
notice, this list of conditions and the following disclaimer.
|
||
|
2. Redistributions in binary form must reproduce the above copyright
|
||
|
notice, this list of conditions and the following disclaimer in the
|
||
|
documentation and/or other materials provided with the distribution.
|
||
|
|
||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
||
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
*/
|
||
|
|
||
|
#ifndef _HCL_XMA_H_
|
||
|
#define _HCL_XMA_H_
|
||
|
|
||
|
/** @file
|
||
|
* This file defines an extravagant memory allocator. Why? It may be so.
|
||
|
* The memory allocator allows you to maintain memory blocks from a
|
||
|
* larger memory chunk allocated with an outer memory allocator.
|
||
|
* Typically, an outer memory allocator is a standard memory allocator
|
||
|
* like malloc(). You can isolate memory blocks into a particular chunk.
|
||
|
*
|
||
|
* See the example below. Note it omits error handling.
|
||
|
*
|
||
|
* @code
|
||
|
* #include <hcl-xma.h>
|
||
|
* #include <stdio.h>
|
||
|
* #include <stdarg.h>
|
||
|
* void dumper (void* ctx, const char* fmt, ...)
|
||
|
* {
|
||
|
* va_list ap;
|
||
|
* va_start (ap, fmt);
|
||
|
* vfprintf (fmt, ap);
|
||
|
* va_end (ap);
|
||
|
* }
|
||
|
* int main ()
|
||
|
* {
|
||
|
* hcl_xma_t* xma;
|
||
|
* void* ptr1, * ptr2;
|
||
|
*
|
||
|
* // create a new memory allocator obtaining a 100K byte zone
|
||
|
* // with the default memory allocator
|
||
|
* xma = hcl_xma_open(HCL_NULL, 0, 100000L);
|
||
|
*
|
||
|
* ptr1 = hcl_xma_alloc(xma, 5000); // allocate a 5K block from the zone
|
||
|
* ptr2 = hcl_xma_alloc(xma, 1000); // allocate a 1K block from the zone
|
||
|
* ptr1 = hcl_xma_realloc(xma, ptr1, 6000); // resize the 5K block to 6K.
|
||
|
*
|
||
|
* hcl_xma_dump (xma, dumper, HCL_NULL); // dump memory blocks
|
||
|
*
|
||
|
* // the following two lines are not actually needed as the allocator
|
||
|
* // is closed after them.
|
||
|
* hcl_xma_free (xma, ptr2); // dispose of the 1K block
|
||
|
* hcl_xma_free (xma, ptr1); // dispose of the 6K block
|
||
|
*
|
||
|
* hcl_xma_close (xma); // destroy the memory allocator
|
||
|
* return 0;
|
||
|
* }
|
||
|
* @endcode
|
||
|
*/
|
||
|
#include <hcl-cmn.h>
|
||
|
|
||
|
#ifdef HCL_BUILD_DEBUG
|
||
|
# define HCL_XMA_ENABLE_STAT
|
||
|
#endif
|
||
|
|
||
|
/** @struct hcl_xma_t
|
||
|
* The hcl_xma_t type defines a simple memory allocator over a memory zone.
|
||
|
* It can obtain a relatively large zone of memory and manage it.
|
||
|
*/
|
||
|
typedef struct hcl_xma_t hcl_xma_t;
|
||
|
|
||
|
/**
|
||
|
* The hcl_xma_fblk_t type defines a memory block allocated.
|
||
|
*/
|
||
|
typedef struct hcl_xma_fblk_t hcl_xma_fblk_t;
|
||
|
typedef struct hcl_xma_mblk_t hcl_xma_mblk_t;
|
||
|
|
||
|
#define HCL_XMA_FIXED 32
|
||
|
#define HCL_XMA_SIZE_BITS ((HCL_SIZEOF_OOW_T*8)-1)
|
||
|
|
||
|
struct hcl_xma_t
|
||
|
{
|
||
|
hcl_mmgr_t* _mmgr;
|
||
|
|
||
|
hcl_uint8_t* start; /* zone beginning */
|
||
|
hcl_uint8_t* end; /* zone end */
|
||
|
int internal;
|
||
|
|
||
|
/** pointer array to free memory blocks */
|
||
|
hcl_xma_fblk_t* xfree[HCL_XMA_FIXED + HCL_XMA_SIZE_BITS + 1];
|
||
|
|
||
|
/** pre-computed value for fast xfree index calculation */
|
||
|
hcl_oow_t bdec;
|
||
|
|
||
|
#ifdef HCL_XMA_ENABLE_STAT
|
||
|
struct
|
||
|
{
|
||
|
hcl_oow_t total;
|
||
|
hcl_oow_t alloc;
|
||
|
hcl_oow_t avail;
|
||
|
hcl_oow_t nused;
|
||
|
hcl_oow_t nfree;
|
||
|
} stat;
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* The hcl_xma_dumper_t type defines a printf-like output function
|
||
|
* for hcl_xma_dump().
|
||
|
*/
|
||
|
typedef void (*hcl_xma_dumper_t) (
|
||
|
void* ctx,
|
||
|
const hcl_bch_t* fmt,
|
||
|
...
|
||
|
);
|
||
|
|
||
|
#if defined(__cplusplus)
|
||
|
extern "C" {
|
||
|
#endif
|
||
|
|
||
|
/**
|
||
|
* The hcl_xma_open() function creates a memory allocator. It obtains a memory
|
||
|
* zone of the @a zonesize bytes with the memory manager @a mmgr. It also makes
|
||
|
* available the extension area of the @a xtnsize bytes that you can get the
|
||
|
* pointer to with hcl_xma_getxtn().
|
||
|
*
|
||
|
* @return pointer to a memory allocator on success, #HCL_NULL on failure
|
||
|
*/
|
||
|
HCL_EXPORT hcl_xma_t* hcl_xma_open (
|
||
|
hcl_mmgr_t* mmgr, /**< memory manager */
|
||
|
hcl_oow_t xtnsize, /**< extension size in bytes */
|
||
|
void* zoneptr,
|
||
|
hcl_oow_t zonesize /**< zone size in bytes */
|
||
|
);
|
||
|
|
||
|
/**
|
||
|
* The hcl_xma_close() function destroys a memory allocator. It also frees
|
||
|
* the memory zone obtained, which invalidates the memory blocks within
|
||
|
* the zone. Call this function to destroy a memory allocator created with
|
||
|
* hcl_xma_open().
|
||
|
*/
|
||
|
HCL_EXPORT void hcl_xma_close (
|
||
|
hcl_xma_t* xma /**< memory allocator */
|
||
|
);
|
||
|
|
||
|
#if defined(HCL_HAVE_INLINE)
|
||
|
static HCL_INLINE hcl_mmgr_t* hcl_xma_getmmgr (hcl_xma_t* xma) { return xma->_mmgr; }
|
||
|
#else
|
||
|
# define hcl_xma_getmmgr(xma) (((hcl_xma_t*)(xma))->_mmgr)
|
||
|
#endif
|
||
|
|
||
|
#if defined(HCL_HAVE_INLINE)
|
||
|
static HCL_INLINE void* hcl_xma_getxtn (hcl_xma_t* xma) { return (void*)(xma + 1); }
|
||
|
#else
|
||
|
#define hcl_xma_getxtn(xma) ((void*)((hcl_xma_t*)(xma) + 1))
|
||
|
#endif
|
||
|
|
||
|
/**
|
||
|
* The hcl_xma_init() initializes a memory allocator. If you have the hcl_xma_t
|
||
|
* structure statically declared or already allocated, you may pass the pointer
|
||
|
* to this function instead of calling hcl_xma_open(). It obtains a memory zone
|
||
|
* of @a zonesize bytes with the memory manager @a mmgr. Unlike hcl_xma_open(),
|
||
|
* it does not accept the extension size, thus not creating an extention area.
|
||
|
* @return 0 on success, -1 on failure
|
||
|
*/
|
||
|
HCL_EXPORT int hcl_xma_init (
|
||
|
hcl_xma_t* xma, /**< memory allocator */
|
||
|
hcl_mmgr_t* mmgr, /**< memory manager */
|
||
|
void* zoneptr, /**< pointer to memory zone. if #HCL_NULL, a zone is auto-created */
|
||
|
hcl_oow_t zonesize /**< zone size in bytes */
|
||
|
);
|
||
|
|
||
|
/**
|
||
|
* The hcl_xma_fini() function finalizes a memory allocator. Call this
|
||
|
* function to finalize a memory allocator initialized with hcl_xma_init().
|
||
|
*/
|
||
|
HCL_EXPORT void hcl_xma_fini (
|
||
|
hcl_xma_t* xma /**< memory allocator */
|
||
|
);
|
||
|
|
||
|
/**
|
||
|
* The hcl_xma_alloc() function allocates @a size bytes.
|
||
|
* @return pointer to a memory block on success, #HCL_NULL on failure
|
||
|
*/
|
||
|
HCL_EXPORT void* hcl_xma_alloc (
|
||
|
hcl_xma_t* xma, /**< memory allocator */
|
||
|
hcl_oow_t size /**< size in bytes */
|
||
|
);
|
||
|
|
||
|
HCL_EXPORT void* hcl_xma_calloc (
|
||
|
hcl_xma_t* xma,
|
||
|
hcl_oow_t size
|
||
|
);
|
||
|
|
||
|
/**
|
||
|
* The hcl_xma_alloc() function resizes the memory block @a b to @a size bytes.
|
||
|
* @return pointer to a resized memory block on success, #HCL_NULL on failure
|
||
|
*/
|
||
|
HCL_EXPORT void* hcl_xma_realloc (
|
||
|
hcl_xma_t* xma, /**< memory allocator */
|
||
|
void* b, /**< memory block */
|
||
|
hcl_oow_t size /**< new size in bytes */
|
||
|
);
|
||
|
|
||
|
/**
|
||
|
* The hcl_xma_alloc() function frees the memory block @a b.
|
||
|
*/
|
||
|
HCL_EXPORT void hcl_xma_free (
|
||
|
hcl_xma_t* xma, /**< memory allocator */
|
||
|
void* b /**< memory block */
|
||
|
);
|
||
|
|
||
|
/**
|
||
|
* The hcl_xma_dump() function dumps the contents of the memory zone
|
||
|
* with the output function @a dumper provided. The debug build shows
|
||
|
* more statistical counters.
|
||
|
*/
|
||
|
HCL_EXPORT void hcl_xma_dump (
|
||
|
hcl_xma_t* xma, /**< memory allocator */
|
||
|
hcl_xma_dumper_t dumper, /**< output function */
|
||
|
void* ctx /**< first parameter to output function */
|
||
|
);
|
||
|
|
||
|
#if defined(__cplusplus)
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#endif
|