enhanced qse_fma_h to have more consistency with qse_xma_h

This commit is contained in:
2010-08-27 00:26:28 +00:00
parent 530ab74909
commit 810134f0ea
23 changed files with 422 additions and 207 deletions

View File

@ -22,20 +22,21 @@
#define _QSE_CMN_FMA_H_
/** @file
* This file defines a fixed-size block memory allocator. As the block size
* is known in advance, it achieves block allocation with little overhead.
* This file defines a fixed-size block memory allocator.
* As the block size is known in advance, it achieves block allocation
* with little overhead.
*
* <pre>
* chunk head(cnkhead)
* | chunk
* |
* | +---------------------------------------------+
* +--> | | f1 | f2 | | |
* +--> | | f1 | f2 | | | chunk #2
* +--|---------^------|----^--------------------+
* | | | |
* | +------+ +---+ +--------------+ chunk
* | +------+ +---+ +--------------+
* | | | |
* | +-----------------|----V--------------|-------+
* +---> | | | f3 | | f4 |
* +---> | | | f3 | | f4 | chunk #1
* +---------------------------------------^-----+
* |
* free block head (freeblk)
@ -44,8 +45,122 @@
* The diagram above assumes that f1, f2, f3, and f4 are free blocks.
* The chaining order depends on the allocation and deallocation order.
*
* See #qse_fma_t for more information. Use #qse_xma_t for variable-size block
* allocation.
* See an example below. Note that it omits error handling.
*
* @code
* #include <qse/cmn/fma.h>
* int main ()
* {
* qse_fma_t* fma;
* int* ptr1, * ptr2;
*
* // create a memory allocator for integer blocks up to 50.
* fma = qse_fma_open (QSE_NULL, 0, sizeof(int), 10, 5);
*
* // allocate two integer blocks
* ptr1 = (int*) qse_fma_alloc (fma, sizeof(int));
* ptr2 = (int*) qse_fma_alloc (fma, sizeof(int));
*
* *ptr1 = 20; *ptr2 = 99;
*
* // free the two blocks.
* qse_fma_free (fma, ptr1);
* qse_fma_free (fma, ptr2);
*
* // destroy the memory allocator
* qse_fma_close (fma);
* }
* @endcode
*
* The following example shows how to use the fixed-size block
* allocator for a dynamic data structure allocating fixed-size nodes.
*
* @code
* #include <qse/cmn/fma.h>
* #include <qse/cmn/rbt.h>
* #include <qse/cmn/mem.h>
* #include <qse/cmn/stdio.h>
*
* static qse_rbt_walk_t walk (qse_rbt_t* rbt, qse_rbt_pair_t* pair, void* ctx)
* {
* qse_printf (QSE_T("key = %lld, value = %lld\n"),
* *(long*)QSE_RBT_KPTR(pair), *(long*)QSE_RBT_VPTR(pair));
* return QSE_RBT_WALK_FORWARD;
* }
*
* int main ()
* {
* qse_fma_t* fma;
* qse_rbt_t rbt;
* qse_size_t blksize;
* long x;
*
* // prepare the fixed-size block allocator into the qse_mmgr_t interface
* qse_mmgr_t mmgr =
* {
* (qse_mmgr_alloc_t) qse_fma_alloc,
* (qse_mmgr_realloc_t) qse_fma_realloc,
* (qse_mmgr_free_t) qse_fma_free,
* QSE_NULL
* };
*
* // the block size of a red-black tree is fixed to be:
* // key size + value size + internal node size.
* blksize = sizeof(long) + sizeof(long) + sizeof(qse_rbt_pair_t);
*
* // create a fixed-size block allocator which is created
* // with the default memory allocator.
* fma = qse_fma_open (QSE_MMGR_GETDFL(), 0, blksize, 10, 0);
* if (fma == QSE_NULL)
* {
* qse_printf (QSE_T("cannot open a memory allocator\n"));
* return -1;
* }
*
* // complete the qse_mmgr_t interface by providing the allocator.
* mmgr.udd = fma;
*
* // initializes the statically declared red-black tree.
* // can not call qse_rbt_open() which allocates the qse_rbt_t object.
* // as its size differs from the block size calculated above.
* if (qse_rbt_init (&rbt, &mmgr) == QSE_NULL)
* {
* qse_printf (QSE_T("cannot initialize a tree\n"));
* qse_fma_close (fma);
* return -1;
* }
*
* // perform more initializations for keys and values.
* qse_rbt_setcopier (&rbt, QSE_RBT_KEY, QSE_RBT_COPIER_INLINE);
* qse_rbt_setcopier (&rbt, QSE_RBT_VAL, QSE_RBT_COPIER_INLINE);
* qse_rbt_setscale (&rbt, QSE_RBT_KEY, QSE_SIZEOF(long));
* qse_rbt_setscale (&rbt, QSE_RBT_VAL, QSE_SIZEOF(long));
*
* // insert numbers into the red-black tree
* for (x = 10; x < 100; x++)
* {
* long y = x * x;
* if (qse_rbt_insert (&rbt, &x, 1, &y, 1) == QSE_NULL)
* {
* qse_printf (QSE_T("failed to insert. out of memory\n"));
* break;
* }
* }
*
* // print the tree contents
* qse_rbt_walk (&rbt, walk, QSE_NULL);
*
* // finalize the tree.
* qse_rbt_fini (&rbt);
*
* // destroy the memory allocator.
* qse_fma_close (fma);
*
* return 0;
* }
* @endcode
*
* Use #qse_xma_t for variable-size block allocation.
*/
#include <qse/types.h>
@ -73,27 +188,6 @@ struct qse_fma_blk_t
/** @struct qse_fma_t
* The qse_fma_t type defines a fixed-size block memory allocator.
* See the example below. Note that it omits error handling.
* @code
* qse_fma_t* fma;
* int* ptr1, * ptr2;
*
* // create a memory allocator for integer blocks up to 50.
* fma = qse_fma_open (QSE_NULL, 0, sizeof(int), 10, 5);
*
* // allocate two integer blocks
* ptr1 = (int*) qse_fma_alloc (fma);
* ptr2 = (int*) qse_fma_alloc (fma);
*
* *ptr1 = 20; *ptr2 = 99;
*
* // free the two blocks.
* qse_fma_free (fma, ptr1);
* qse_fma_free (fma, ptr2);
*
* // destroy the memory allocator
* qse_fma_close (fma);
* @endcode
*/
typedef struct qse_fma_t qse_fma_t;
struct qse_fma_t
@ -122,9 +216,9 @@ QSE_DEFINE_COMMON_FUNCTIONS (fma)
qse_fma_t* qse_fma_open (
qse_mmgr_t* mmgr, /**< outer memory manager */
qse_size_t xtnsize, /**< extension size in bytes */
qse_size_t blksize, /**< block size in bytes */
qse_size_t blksize, /**< fixed block size in bytes */
qse_size_t maxblks, /**< maximum numbers of blocks in a chunk */
qse_size_t maxcnks /**< maximum numbers of chunks */
qse_size_t maxcnks /**< maximum numbers of chunks. 0 for no limit */
);
/**
@ -135,14 +229,15 @@ void qse_fma_close (
);
/**
* The qse_fma_init() function initializes an memory allocator.
* The qse_fma_init() function initializes an memory allocator statically
* declared.
*/
qse_fma_t* qse_fma_init (
qse_fma_t* fma, /**< memory allocator */
qse_mmgr_t* mmgr, /**< outer memory manager */
qse_size_t blksize, /**< block size in bytes */
qse_size_t blksize, /**< fixed block size in bytes */
qse_size_t maxblks, /**< maximum numbers of blocks in a chunk */
qse_size_t maxcnks /**< maximum numbers of chunks */
qse_size_t maxcnks /**< maximum numbers of chunks. 0 for no limit */
);
/**
@ -153,15 +248,41 @@ void qse_fma_fini (
);
/**
* The qse_fma_alloc() function allocates a block.
* @return block pointer on success, QSE_NULL on failure
* The qse_fma_alloc() function allocates a block of the fixed block size
* specified during initialization regardless of the block size @a size
* requested so long as it is not greater than the fixed size. The function
* fails if it is greater.
*
* @return block pointer on success, #QSE_NULL on failure
*/
void* qse_fma_alloc (
qse_fma_t* fma /**< memory allocator */
qse_fma_t* fma, /**< memory allocator */
qse_size_t size /**< block size in bytes*/
);
/**
* The qse_fma_alloc() function deallocates a block.
* The qse_fma_realloc() function is provided for consistency with other
* generic memory allocator which provides a reallocation function.
* Block resizing is meaningless for #qse_fma_t as it deals with fixed-size
* blocks.
*
* If the @a size requested is greater than the fixed block size of the memory
* allocator @a fma, the function fails; If the block @a blk is #QSE_NULL and
* the @a size requested is not greater than the fixed block size of the memory
* allocator @a fma, it allocates a block of the fixed size; If the block
* @a blk is not #QSE_NULL and the @a size requested is not greater than the
* fixed block size of the memory allocator @a fma, it returns the block @blk.
*
* @return block pointer on success, #QSE_NULL on failure
*/
void* qse_fma_realloc (
qse_fma_t* fma, /**< memory allocator */
void* blk, /**< memory block */
qse_size_t size /**< block size in bytes*/
);
/**
* The qse_fma_free() function deallocates a block.
*/
void qse_fma_free (
qse_fma_t* fma, /**< memory allocator */

View File

@ -1,5 +1,5 @@
/*
* $Id: mem.h 287 2009-09-15 10:01:02Z hyunghwan.chung $
* $Id: mem.h 348 2010-08-26 06:26:28Z hyunghwan.chung $
*
Copyright 2006-2009 Chung, Hyung-Hwan.
This file is part of QSE.
@ -21,13 +21,21 @@
#ifndef _QSE_CMN_MEM_H_
#define _QSE_CMN_MEM_H_
/** @file
* This file defines functions and macros for memory manipulation.
*/
#include <qse/types.h>
#include <qse/macros.h>
/* gets a pointer to the default memory manager */
/**
* The QSE_MMGR_GETDFL() macro returns the default memory manager.
*/
#define QSE_MMGR_GETDFL() (qse_mmgr)
/* sets a pointer to the default memory manager */
/**
* The QSE_MMGR_SETDFL() macro changes the default memory manager.
*/
#define QSE_MMGR_SETDFL(m) ((qse_mmgr)=(m))
/* allocate a memory block */
@ -46,163 +54,128 @@
extern "C" {
#endif
/*
* NAME: holds a pointer to the default memory manager
*
* DESCRIPTION:
* The QSE_MMGR_GETDFL() macro returns the default memory manager.
* You may use QSE_MMGR_SETDFL() to change the default memory manager.
/**
* The qse_mmgr global variable holds a pointer to the default memory
* manager. Use QSE_MMGR_GETDFL() and QSE_MMGR_SETDFL() to manipulate it.
*/
extern qse_mmgr_t* qse_mmgr;
/*
* NAME: copy a memory block
/**
* The qse_memcpy() functions copies @a n bytes from the source memory block
* @a src to the destinaion memory block @a dst. The memory blocks must not
* overlap. Use qse_memmove() if they overlap.
*
* DESCRIPTION:
* The qse_memcpy() functions copies n bytes from the source memory block src
* to the destinaion memory block dst.
*
* RETURNS: the destination memory block dst.
*
* WARNING:
* The memory blocks should not overlap. Use the qse_memmove() function if
* they overlap.
* @return destination memory block @a dst.
*/
void* qse_memcpy (
void* dst /* a pointer to the destination memory block */ ,
const void* src /* a pointer to the source memory block */ ,
qse_size_t n /* the number of bytes to copy */
void* dst, /**< destination memory block */
const void* src, /**< source memory block */
qse_size_t n /**< number of bytes to copy */
);
/*
* NAME: copy a memory block with more care
/**
* The qse_memmove() functions copies @a n bytes from the source memory block
* @a src to the destinaion memory block @a dst without corrupting overlapping
* zone.
*
* DESCRIPTION:
* The qse_memmove() functions copies n bytes from the source memory block src
* to the destinaion memory block dst without corrupting overlapping zone.
*
* RETURNS: the destination memory block dst.
* @return destination memory block @a dst.
*/
void* qse_memmove (
void* dst /* a pointer to the destination memory block */,
const void* src /* a pointer to the source memory block */,
qse_size_t n /* the number of bytes to copy */
void* dst, /**< destination memory block */
const void* src, /**< source memory block */
qse_size_t n /**< number of bytes to copy */
);
/*
* NAME: fill a memory block
* The qse_memset() function fills leading @a n bytes of the destination
* memory block @a dst with the byte @a val.
*
* DESCRIPTION:
* The qse_memset() function fills leading n bytes of the destination
* memory block dst with the byte val.
*
* RETURNS: the destination memory block dst
* @return destination memory block @a dst.
*/
void* qse_memset (
void* dst /* a pointer to the destination memory block */,
int val /* the byte to fill the memory block with */,
qse_size_t n /* the number of bytes to fill */
void* dst, /**< destination memory block */
int val, /**< value fill the memory block with */
qse_size_t n /**< number of bytes to fill */
);
/*
* NAME: compare memory blocks
*
* DESCRIPTION:
* The qse_memcmp() function compares leading n bytes of two memory blocks
* s1 and s2.
/**
* The qse_memcmp() function compares leading *a n bytes of two memory blocks
* @a s1 and @a s2.
*
* RETURNS:
* 0 if two memory ares have the same leadning n bytes.
* a positive number if the first different byte of s1 is greater than that
* of s2.
* a negative number if the first different byte of s1 is less than that of s2.
* @return
* 0 if two memory ares have the same leadning @a n bytes.
* positive number if the first different byte of s1 is greater than that of s2.
* negative number if the first different byte of s1 is less than that of s2.
*/
int qse_memcmp (
const void* s1 /* a pointer to the first memory block to compare */,
const void* s2 /* a pointer to the second memory block to compare */,
qse_size_t n /* the number of bytes to compare */
const void* s1, /**< first memory block to compare */
const void* s2, /**< second memory block to compare */
qse_size_t n /**< the number of bytes to compare */
);
/*
* NAME: find a byte forward in a memory block
*
* DESCRIPTION:
* The qse_membyte() function scans the memory block s from the first byte
* up to the nth byte in search of the byte val. If it finds a match,
* it aborts scanning the memory block and returns the pointer to the matching
* location.
/**
* The qse_membyte() function scans the memory block @a s from the first byte
* up to the nth byte in search of the byte @a val. If it finds a match,
* it aborts scanning the memory block and returns the pointer to the matching
* location.
*
* RETURNS:
* QSE_NULL if the byte val is not found.
* The pointer to the location in the memory block s matching the byte val
* @return
* #QSE_NULL if the byte @a val is not found.
* pointer to the location in the memory block @a s matching the byte @a val
* if a match is found.
*/
void* qse_membyte (
const void* s /* a pointer to the memory block to scan */,
int val /* a byte to find */,
qse_size_t n /* the number of bytes to scan */
const void* s, /**< memory block to scan */
int val, /**< byte to find */
qse_size_t n /**< number of bytes to scan */
);
/*
* NAME: find a byte backward in a memory block
*
* DESCRIPTION:
* The qse_memrbyte() function scans the memory block s from the nth byte
* backward to the first byte in search of the byte val. If it finds a match,
* it aborts scanning the memory block and returns the pointer to the matching
* location.
* The qse_memrbyte() function scans the memory block @a s from the nth byte
* backward to the first byte in search of the byte @a val. If it finds a match,
* it aborts scanning the memory block and returns the pointer to the matching
* location.
*
* RETURNS:
* QSE_NULL if the byte val is not found.
* The pointer to the location in the memory block s matching the byte val
* @return
* #QSE_NULL if the byte val is not found.
* pointer to the location in the memory block s matching the byte val
* if a match is found.
*/
void* qse_memrbyte (
const void* s /* a pointer to the memory block to scan */,
int val /* a byte to find */,
qse_size_t n /* the number of bytes to scan */
const void* s, /**< memory block to scan */
int val, /**< byte to find */
qse_size_t n /**< number of bytes to scan */
);
/*
* NAME: find a block of bytes forward in a memory block
*
* DESCRIPTION:
* The qse_memmem() functions scans the first hl bytes of the memory block hs
* in search of the byte block nd of the length nl bytes.
/**
* The qse_memmem() functions scans the first @a hl bytes of the memory
* block @a hs in search of the byte block @a nd of the length @a nl bytes.
*
* RETURNS:
* QSE_NULL if the byte val is not found.
* The pointer to the location in the memory block s matching the byte val
* if a match is found.
*
* RETURNS:
* QSE_NULL if no match is found.
* The pointer to the start of the matching location if a match is found.
* @return
* #QSE_NULL if no match is found.
* pointer to the start of the matching location if a match is found.
*/
void* qse_memmem (
const void* hs /* a pointer to the memory block to scan */,
qse_size_t hl /* the number of bytes to scan */,
const void* nd /* a pointer to the byte block to find */,
qse_size_t nl /* the number of bytes in the block */
const void* hs, /**< memory block to scan */
qse_size_t hl, /**< number of bytes to scan */
const void* nd, /**< byte block to find */
qse_size_t nl /**< number of bytes in the block */
);
/*
* NAME: find a block of bytes backward in a memory block
* The qse_memrmem() functions scans the first @a hl bytes of the memory
* block @a hs backward in search of the byte block @a nd of the length
* @a nl bytes.
*
* DESCRIPTION:
* The qse_memrmem() functions scans the first hl bytes of the memory block hs
* backward in search of the byte block nd of the length nl bytes.
*
* RETURNS:
* QSE_NULL if no match is found.
* The pointer to the start of the matching location if a match is found.
* @return
* #QSE_NULL if no match is found.
* pointer to the start of the matching location if a match is found.
*/
void* qse_memrmem (
const void* hs /* a pointer to the memory block to scan */,
qse_size_t hl /* the number of bytes to scan */,
const void* nd /* a pointer to the byte block to find */,
qse_size_t nl /* the number of bytes in the block */
const void* hs, /**< memory block to scan */
qse_size_t hl, /**< number of bytes to scan */
const void* nd, /**< byte block to find */
qse_size_t nl /**< number of bytes in the block */
);
#ifdef __cplusplus

View File

@ -1,5 +1,5 @@
/*
* $Id: opt.h 287 2009-09-15 10:01:02Z hyunghwan.chung $
* $Id: opt.h 348 2010-08-26 06:26:28Z hyunghwan.chung $
*
Copyright 2006-2009 Chung, Hyung-Hwan.
This file is part of QSE.
@ -25,7 +25,7 @@
#include <qse/macros.h>
/** @file
* <qse/cmn/opt.h> defines functions and data structures to process
* This file defines functions and data structures to process
* command-line arguments.
*/

View File

@ -22,8 +22,7 @@
#define _QSE_CMN_STDIO_H_
/** @file
* #qse_char_t friendly stdio wrapper functions are defined in this file.
*
* This file defines stdio wrapper functions for #qse_char_t.
*/
#include <qse/types.h>
@ -89,6 +88,9 @@ QSE_FILE* qse_fopen (const qse_char_t* path, const qse_char_t* mode);
QSE_FILE* qse_popen (const qse_char_t* cmd, const qse_char_t* mode);
/**
* The qse_getline() function read a line from a file pointer @a fp
* until a new line character is met.
*
* @return -2 on error, -1 on eof, length of data read on success
*/
qse_ssize_t qse_getline (qse_char_t **buf, qse_size_t *n, QSE_FILE *fp);

View File

@ -27,7 +27,36 @@
* 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 #qse_xma_t for an example.
*
* See the example below. Note it omits error handling.
*
* @code
* #include <qse/cmn/xma.h>
* #include <qse/cmn/stdio.h>
* int main ()
* {
* qse_xma_t* xma;
* void* ptr1, * ptr2;
*
* // create a new memory allocator obtaining a 100K byte zone
* // with the default memory allocator
* xma = qse_xma_open (QSE_NULL, 0, 100000L);
*
* ptr1 = qse_xma_alloc (xma, 5000); // allocate a 5K block from the zone
* ptr2 = qse_xma_alloc (xma, 1000); // allocate a 1K block from the zone
* ptr1 = qse_xma_realloc (xma, ptr1, 6000); // resize the 5K block to 6K.
*
* qse_xma_dump (xma, qse_printf); // dump memory blocks
*
* // the following two lines are not actually needed as the allocator
* // is closed after them.
* qse_xma_free (xma, ptr2); // dispose of the 1K block
* qse_xma_free (xma, ptr1); // dispose of the 6K block
*
* qse_xma_close (xma); // destroy the memory allocator
* return 0;
* }
* @endcode
*/
#include <qse/types.h>
#include <qse/macros.h>
@ -39,28 +68,6 @@
/** @struct qse_xma_t
* The qse_xma_t type defines a simple memory allocator over a memory zone.
* It can obtain a relatively large zone of memory and manage it.
*
* @code
* qse_xma_t* xma;
* void* ptr1, * ptr2;
*
* // create a new memory allocator obtaining a 100K byte zone
* // with the default memory allocator
* xma = qse_xma_open (QSE_NULL, 0, 100000L);
*
* ptr1 = qse_xma_alloc (xma, 5000); // allocate a 5K block from the zone
* ptr2 = qse_xma_alloc (xma, 1000); // allocate a 1K block from the zone
* ptr1 = qse_xma_realloc (xma, ptr1, 6000); // resize the 5K block to 6K.
*
* qse_xma_dump (xma, qse_printf); // dump memory blocks
*
* // the following two lines are not actually needed as the allocator
* // is closed after them.
* qse_xma_free (xma, ptr2); // dispose of the 1K block
* qse_xma_free (xma, ptr1); // dispose of the 6K block
*
* qse_xma_close (xma); // destroy the memory allocator
* @endcode
*/
typedef struct qse_xma_t qse_xma_t;

View File

@ -1,5 +1,5 @@
/*
* $Id: macros.h 338 2010-07-30 13:24:19Z hyunghwan.chung $
* $Id: macros.h 348 2010-08-26 06:26:28Z hyunghwan.chung $
*
Copyright 2006-2009 Chung, Hyung-Hwan.
This file is part of QSE.
@ -24,7 +24,7 @@
#include <qse/types.h>
/** @file
* <qse/macros.h> contains various useful macro definitions.
* This file contains various useful macro definitions.
*/
#if defined(__STDC_VERSION__) && (__STDC_VERSION__>=199901L)

View File

@ -1,5 +1,5 @@
/*
* $Id: types.h 338 2010-07-30 13:24:19Z hyunghwan.chung $
* $Id: types.h 348 2010-08-26 06:26:28Z hyunghwan.chung $
*
Copyright 2006-2009 Chung, Hyung-Hwan.
This file is part of QSE.
@ -22,7 +22,7 @@
#define _QSE_TYPES_H_
/**@file
* <qse/types.h> defines various common basic types designed to be
* This file defines various common basic types designed to be
* cross-platform. These types are preferred over native data types.
*/