eg_mem.h

Go to the documentation of this file.
00001 /* EGlib "Efficient General Library" provides some basic structures and
00002  * algorithms commons in many optimization algorithms.
00003  *
00004  * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
00005  * 
00006  * This library is free software; you can redistribute it and/or modify it
00007  * under the terms of the GNU Lesser General Public License as published by the
00008  * Free Software Foundation; either version 2.1 of the License, or (at your
00009  * option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful, but 
00012  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
00013  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
00014  * License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public License
00017  * along with this library; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
00019  * */
00020 /* ========================================================================= */
00021 /** @defgroup EGmem EGmem
00022  *
00023  * Here we define some usefull macros to deal with memory issues, for example,
00024  * assert that we always return memory when posible, and if no memory is found,
00025  * then we just exit to the system (because if there is trully no memory....
00026  * there is no much else to do... unless we start using shrinkable memory
00027  * pools, like for example @ref EGmemSlab , but that is still a long way off,
00028  * it will also perform (if debugging enabled) some allocation / freeing
00029  * checkings and so on.
00030  *
00031  * @version 0.0.1
00032  * @par History:
00033  * -2005-09-05
00034  *          - Add EGrealloc, wich is a wrapper of realloc but that assures us
00035  *          to have memory, if there is no  memory, we exit. The idea of these
00036  *          functions is that in the future they would interact with the
00037  *          memory pools to use any memory still in the pools.
00038  * -2005-08-20
00039  *          - Move memory align definitions here, and set the aligment of
00040  *            memory to 8 bytes (i.e. 64 bits). This is to simplify compilation
00041  *            in diferent architectures like Sun, opteron 64 and intel 32.
00042  * -2005-08-01
00043  *          - Fix calloc call to the right type (size_t), and some printing
00044  *            issues while compiling on 64-bit architectures.
00045  * -2005-07-30
00046  *          - First Implementation
00047  * */
00048 /** @file
00049  * @ingroup EGmem */
00050 /** @addtogroup EGmem */
00051 /** @{ */
00052 #ifndef __EG_MEM_H__
00053 #define __EG_MEM_H__
00054 #include "eg_config.h"
00055 #include "eg_macros.h"
00056 
00057 /* ========================================================================= */
00058 /** @brief size of a normal word in this machine (a word is just big enough to
00059  * store a pointer) */
00060 #define EG_MEM_WORD_SIZE (sizeof(void*))
00061 /* ========================================================================= */
00062 /** @brief memory aligment used by EG alloc functions. */
00063 #define EG_MEM_ALIGNMENT 8U
00064 
00065 /* ========================================================================= */
00066 /** @brief \f$log_2(EG_MEM_ALIGNMENT)\f$. */
00067 #define EG_MEM_ALIGNMENT_SHIFT 3U
00068 
00069 /* ========================================================================= */
00070 /** @brief Given a pointer, return it's aligned value. */
00071 #define EG_MEM_ALIGN(__ptr) \
00072   ((((size_t)__ptr)+EG_MEM_ALIGNMENT-1)&(~(EG_MEM_ALIGNMENT-1)))
00073 
00074 /* ========================================================================= */
00075 /** @brief type of the free functions that recive only one parameter */
00076 typedef void (*EGfree_f) (void *);
00077 
00078 /* ========================================================================= */
00079 /** @brief this is the the data free that does nothing, use it when you don't 
00080  * want/need to free the internal list data becouse you will do it 
00081  * elsewere */
00082 #define nullFree ((EGfree_f)0)
00083 
00084 /* ========================================================================= */
00085 /** @brief custom allocation functions prototype: This class of functions
00086  * receive some user-provided data (udata), and given a size (psz), return a pointer of the given size */
00087 typedef void*(*EGualloc_f)(void*udata,size_t psz);
00088 
00089 /* ========================================================================= */
00090 /** @brief custom free functions prototype: This class of functions receive
00091  * some user-provided data (udata), and a pointer (ptr), and should free (or
00092  * manage de-alocation) of the provided pointer. */
00093 typedef void (*EGufree_f)(void*udata,void*ptr);
00094 
00095 /* ========================================================================= */
00096 /** @brief type for constructor functions. Given a pointer to an element of
00097  * some type, do the internal initialization necesary so that we can work with
00098  * the lement, such initialization may include allocating some internal memory
00099  * needed by the structure (not done by the user). This functions must never
00100  * fail. if some unexpected error does happen inside, then the function should
00101  * not return. (a call to exit(1) would do the trick). */
00102 typedef void (*EGconstructor_f) (void *);
00103 
00104 /* ========================================================================= */
00105 /** @brief Null constructor function (do nothing) */
00106 #define nullConstructor ((EGconstructor_f)0)
00107 
00108 /* ========================================================================= */
00109 /** @brief type for destructor functions. Given a pointer to an element of some
00110  * type, free all internal memory related to the element allocated during the
00111  * construction phase. (but not the pointer itself). This function must always
00112  * succed, if an error happen, the function should never return. (a call to
00113  * exit(1) would do the trick). */
00114 typedef void (*EGdestructor_f) (void *);
00115 
00116 /* ========================================================================= */
00117 /** @brief Null destructor function (do nothing) */
00118 #define nullDestructor ((EGdestructor_f)0)
00119 
00120 /* ========================================================================= */
00121 /** @brief this function replace malloc, check if the memory is not zero, if 
00122  * it is, it exit from the program, and display who called it and how much 
00123  * memory it tryed to alloc.
00124  * @param __A number of bytes to allocate.
00125  * @return a void* pointer to the newly allocated memory, note that if the 
00126  * function returns at all, it will return with the amount of memory required, 
00127  * so no NULL checking is ever necesary after an EGmalloc call. 
00128  * */
00129 #define EGmalloc(__A) ({\
00130   size_t const _EGmp_sz_ = (size_t)(__A);\
00131   void * _EGmp_res_ = 0;\
00132   /*WARNINGL(0,!_EGmp_sz_,"Allocating 0 bytes");*/\
00133   if(_EGmp_sz_)\
00134   {\
00135     _EGmp_res_ = calloc((size_t)1,_EGmp_sz_);\
00136     EXIT(!_EGmp_res_,"Not enough memory while allocating %zd bytes",_EGmp_sz_);\
00137   }\
00138   _EGmp_res_;})
00139 
00140 /* ========================================================================= */
00141 /** @brief This function allocate 'count' elements of type 'type' and return 
00142  * a pointer of type 'type*'. If the memory is not available the program will 
00143  * exit indicating where it was trying to get memory and how much, it will also
00144  * check some common errors like allocating zero bytes.
00145  * @param __type type of the element required.
00146  * @param __count number of contiguous elements of the given type required.
00147  * @return pointer to the beggining of the allocated array of the apropiate
00148  * type (so no casting is needed). Note that if this function returns at all,
00149  * then the memory has been allocated and thus no NULL checking return is
00150  * necesary. */
00151 #define EGsMalloc(__type,__count) (__type*)EGmalloc(sizeof(__type)*((size_t)(__count)))
00152 
00153 /* ========================================================================= */
00154 /** @brief Realloc a given pointer to the new size, and check that we find
00155  * enough memory to return. If we don't, we exit the execution.
00156  * @param __ptr pointer to reallocate.
00157  * @param __sz new number of bytes to reallocate.
00158  * @return pointer to the new block of memory */
00159 #define EGrealloc(__ptr,__sz) ({\
00160   const size_t ____sz = (size_t)(__sz);\
00161   (__ptr) = realloc((__ptr),____sz);\
00162   EXIT(!(__ptr)&&(____sz),"not enough memory while reallocating %zd",____sz);\
00163   (__ptr);})
00164 
00165 /* ========================================================================= */
00166 /** @brief this is used to enable malloc/free tracking and extra debugging */
00167 #ifndef __EG_MEM_FREE_CHECK__
00168 #define __EG_MEM_FREE_CHECK__  (1 && DEBUG)
00169 #endif
00170 
00171 /* ========================================================================= */
00172 /** @brief This function replace free, the idea of this is to HOPEFULLY later 
00173  * develop a memory leack checker that tell us who and where asked for memory 
00174  * and didn't free it, in hte meantime they do nothing.
00175  * @param __A pointer to the piece of memory to be freed, if debuging is enabled,
00176  * the function will test for freing NULL pointers, for suspicios address
00177  * freing and so on. note that the given pointer will point to NULL after this
00178  * call, thus reducing the posibility of freeing multiple times the same piece
00179  * of memory, or of allocating it after freeing it. */
00180 #if __EG_MEM_FREE_CHECK__
00181 #define EGfree(__A) ({\
00182     EXIT(((__A) && !(((size_t)(__A))>>19)),"Trying to free pointer "#__A\
00183         " with value %zd\nThis is probably an error",(size_t)(__A));\
00184     if(__A) free(__A);\
00185     else WARNING(1,"Trying to free "#__A", a NULL pointer");\
00186     (__A) = 0;})
00187 #else
00188 #define EGfree(__A) ({free(__A);(__A)=0;})
00189 #endif
00190 
00191 /* ========================================================================= */
00192 /* end of eg_mem.h */
00193 /** @} */
00194 #endif