Advanced Memory Handling¶
The allocation scheme used in libmpdec allows for mixing statically
and dynamically allocated decimals. If a decimal with a static coefficient
needs to grow beyond the fixed array size, the coefficient automatically
switches to dynamic memory. This is very fast in practice and eliminates
the need for alloca.
It is not necessary to read this section if only dynamically allocated decimals are used.
Static and Dynamic Decimals¶
Static and dynamic decimals may be mixed freely. In particular, they may
be used in the position of the result operand or passed as an argument
to mpd_del.
The coefficient of a static decimal must have the size MPD_MINALLOC_MAX
(see below).
MPD_STATICif set, the
mpd_tstruct is static
MPD_STATIC_DATAif set, the coefficient is static
MPD_MINALLOC¶
In order to avoid frequent resizing operations, the global variable
MPD_MINALLOC guarantees a minimum amount of allocated words for
the coefficient of each mpd_t. The variable can be set once
at program start and all memory functions respect it. The minimum value
for MPD_MINALLOC is MPD_MINALLOC_MIN = 2, the maximum value
is MPD_MINALLOC_MAX = 64.
voidmpd_setminalloc(mpd_ssize_tn);
At program start, set MPD_MINALLOC to n. If n is outside the
limits, the function prints an error and exits. If an attempt is made to
set MPD_MINALLOC a second time, the function does nothing but
print a warning.
Resizing Decimals¶
When writing functions that operate directly on the data of a decimal, it is necessary to resize the coefficient. All the above functions may be called on static decimals, since they are smart enough to allocate dynamic storage if the static array is too small. The functions must not be called on constant or shared decimals.
intmpd_qresize(mpd_t*result,mpd_ssize_tsize,uint32_t*status); intmpd_resize(mpd_t*result,mpd_ssize_tsize,mpd_context_t*ctx); intmpd_qresize_zero(mpd_t*result,mpd_ssize_tsize,uint32_t*status); intmpd_resize_zero(mpd_t*result,mpd_ssize_tsize,mpd_context_t*ctx);
mpd_qresize tries to resize result to size words. If the size is
increased, the existing coefficient data is left untouched. On success, 1
is returned. On failure, 0 is returned and MPD_Malloc_error is
added to the status parameter.
mpd_qresize_zero is the same, but initializes the complete
coefficient - including the old memory area - to zero.
voidmpd_minalloc(mpd_t*result);
Reduce the size of the coefficient to MPD_MINALLOC words. This
function cannot fail.
Custom Allocation Functions¶
externvoid*(*mpd_mallocfunc)(size_tsize); externvoid*(*mpd_callocfunc)(size_tnmemb,size_tsize); externvoid*(*mpd_reallocfunc)(void*ptr,size_tsize); externvoid(*mpd_free)(void*ptr);
At program start, these variables can be set to custom memory allocation functions. By default, they are set to the standard C functions.
void*mpd_alloc(mpd_size_tnmemb,mpd_size_tsize); void*mpd_calloc(mpd_size_tnmemb,mpd_size_tsize);
Memory allocation with overflow checking, using the custom allocation
functions. If the allocation fails or an overflow occurs, return
NULL.
void*mpd_realloc(void*ptr,mpd_size_tnmemb,mpd_size_tsize, uint8_t*err);
If successful, return the pointer to the new memory area. Otherwise, return ptr and set err to 1.
Overflow handling as above.
/* struct hack alloc */ void*mpd_sh_alloc(mpd_size_tstruct_size,mpd_size_tnmemb, mpd_size_tsize);
Like mpd_alloc, with an additional parameter for struct hack
allocations.