00001 /* 00002 * Copyright (c) 1998 by Tech Soft 3D, LLC. 00003 * The information contained herein is confidential and proprietary to 00004 * Tech Soft 3D, LLC., and considered a trade secret as defined under 00005 * civil and criminal statutes. Tech Soft 3D shall pursue its civil 00006 * and criminal remedies in the event of unauthorized use or misappropriation 00007 * of its trade secrets. Use of this information by anyone other than 00008 * authorized employees of Tech Soft 3D, LLC. is granted only under a 00009 * written non-disclosure agreement, expressly prescribing the scope and 00010 * manner of such use. 00011 * 00012 * $Id: hoops__memory_8h-source.html,v 1.27 2008-03-10 07:09:28 stage Exp $ 00013 */ 00014 00015 #ifndef HOOPS_MEMORY_DEFINED 00016 00017 00018 EXTERNAL void * HC_CDECL HI_Allocate (long size, bool allow_failure, HT_Memory_Pool *mempool); 00019 EXTERNAL void * HC_CDECL HI_QAllocate (long islot, HT_Memory_Pool *mempool); 00020 EXTERNAL void HC_CDECL HI_QValidate(char const* file, int line, void * p, long size, bool alloc); 00021 EXTERNAL void * HC_CDECL HI_Really_Allocate (long size, bool allow_failure); 00022 EXTERNAL void HC_CDECL HI_Free (void *p, long size); 00023 EXTERNAL void HC_CDECL HI_Really_Free (void *pntr, long size); 00024 EXTERNAL void HI_Free_Array(void* p, long size, HT_Memory_Pool *mempool); 00025 EXTERNAL void* HI_Alloc_Array(int size, bool try_alloc, HT_Memory_Pool *mempool); 00026 00027 00028 00029 #ifdef SLOW_MEMORY /* define this (worldwide) to avoid the "quick" allocater */ 00030 # define ALLOC_ARRAY(p, count, type) do { \ 00031 H_LOCK_MUTEX_LOW (OUR (memory_mutex)); \ 00032 (p = (type *)HI_Allocate ((count)*(long)sizeof(type), false), OUR(memory_pool)); \ 00033 H_UNLOCK_MUTEX_LOW (OUR (memory_mutex)); \ 00034 } while (0) 00035 # define TRY_ALLOC_ARRAY(p, count, type) do { \ 00036 H_LOCK_MUTEX_LOW (OUR (memory_mutex)); \ 00037 (p = (type *)HI_Allocate ((count)*(long)sizeof(type), true), OUR(memory_pool)); \ 00038 H_UNLOCK_MUTEX_LOW (OUR (memory_mutex)); \ 00039 } while (0) 00040 # define FREE_ARRAY(p, count, type) do { \ 00041 H_LOCK_MUTEX_LOW (OUR (memory_mutex)); \ 00042 HI_Free ((void *)p, (count)*(long)sizeof(type)); \ 00043 H_UNLOCK_MUTEX_LOW (OUR (memory_mutex)); \ 00044 } while (0) 00045 # define ALLOC(p, type) ALLOC_ARRAY(p, 1, type) 00046 # define FREE(p, type) FREE_ARRAY(p, 1, type) 00047 # define POOL_ALLOC_ARRAY(p, count, type, pool) ALLOC_ARRAY(p, count, type) 00048 # define POOL_TRY_ALLOC_ARRAY(p, count, type, pool) TRY_ALLOC_ARRAY(p, count, type) 00049 # define POOL_ALLOC(p, type, pool) ALLOC(p, type) 00050 # define POOL_FREE_ARRAY(p, count, type, pool) FREE_ARRAY(p, count, type) 00051 # define POOL_FREE(p, type, pool) FREE(p, type) 00052 #else 00053 # ifdef RAW_MEMORY 00054 #if 0 00055 /* This is for getting more info on memory leaks in visual studio. Just be sure that 00056 crtdbg.h is included *AFTER* stdlib in all the files where memory is allocated/freed 00057 as crtdbg.h redefined malloc, alloc, calloc, realloc and free. */ 00058 # define _CRTDBG_MAP_ALLOC 00059 # include <stdlib.h> 00060 # include <crtdbg.h> 00061 #else 00062 # include <stdlib.h> 00063 #endif 00064 # define ALLOC_ARRAY(p, count, type) do { \ 00065 p = (type *)malloc((count) * sizeof(type)); \ 00066 OUR(raw_memory_usage) += (sizeof(type) * (count)); \ 00067 } while (0) 00068 # define TRY_ALLOC_ARRAY(p, count, type) ALLOC_ARRAY(p, count, type) 00069 # define FREE_ARRAY(p, count, type) do { \ 00070 OUR(raw_memory_usage) -= (sizeof(type) * (count)); \ 00071 free((void *)(p)); \ 00072 } while (0) 00073 # define ALLOC(p, type) ALLOC_ARRAY(p, 1, type) 00074 # define FREE(p, type) FREE_ARRAY(p, 1, type) 00075 # define POOL_ALLOC_ARRAY(p, count, type, pool) ALLOC_ARRAY(p, count, type) 00076 # define POOL_TRY_ALLOC_ARRAY(p, count, type, pool) TRY_ALLOC_ARRAY(p, count, type) 00077 # define POOL_ALLOC(p, type, pool) ALLOC(p, type) 00078 # define POOL_FREE_ARRAY(p, count, type, pool) FREE_ARRAY(p, count, type) 00079 # define POOL_FREE(p, type, pool) FREE(p, type) 00080 # else 00081 /* not RAW, not SLOW. This is the normal quick mem code */ 00082 00083 # ifdef VALIDATE_MEMORY 00084 # include <stdio.h> 00085 # define __ALLOC_ARRAY(p, size, typep, trying, mempool) do { \ 00086 p = (typep)HI_Alloc_Array(size, trying, mempool); \ 00087 if (BIT (OUR (debug), SYS_DEBUG_QUICK_MEM_LOGGING)) { \ 00088 if (!OUR(quick_mem_logging_file)) \ 00089 OUR(quick_mem_logging_file)=fopen("qmemlog.txt","wb"); \ 00090 fprintf(OUR(quick_mem_logging_file), "+ %p %p %s %d %ld\n", (void*)mempool, (void*)p, __FILE__, __LINE__, size); \ 00091 } \ 00092 }while (0) 00093 # else 00094 # define __ALLOC_ARRAY(p, size, typep, try, mempool) p = (typep)HI_Alloc_Array(size, try, mempool) 00095 # endif 00096 00097 00098 # define ALLOC(p, type) \ 00099 __ALLOC_ARRAY (p, (long)sizeof(type), type *, false, OUR(memory_pool)) 00100 # define ALLOC_ARRAY(p, count, type) \ 00101 __ALLOC_ARRAY (p, (count)*(long)sizeof(type), type *, false, OUR(memory_pool)) 00102 # define TRY_ALLOC_ARRAY(p, count, type) \ 00103 __ALLOC_ARRAY (p, (count)*(long)sizeof(type), type *, true, OUR(memory_pool)) 00104 00105 # ifdef VALIDATE_MEMORY 00106 # define __FREE_ARRAY(p, size, mempool) do { \ 00107 if (BIT (OUR (debug), SYS_DEBUG_QUICK_MEM_LOGGING)) { \ 00108 if (!OUR(quick_mem_logging_file)) \ 00109 OUR(quick_mem_logging_file)=fopen("qmemlog.txt","wb"); \ 00110 fprintf(OUR(quick_mem_logging_file), "- %p %p %s %d %ld\n", (void*)mempool, (void*)p, __FILE__, __LINE__, size); \ 00111 } \ 00112 HI_Free_Array((void*)p, size, mempool); \ 00113 } while (0) 00114 # else 00115 # define __FREE_ARRAY(p, size, mempool) HI_Free_Array((void*)p, size, mempool) 00116 # endif 00117 00118 # define FREE(p, type) \ 00119 __FREE_ARRAY (p, (long)sizeof(type), OUR(memory_pool)) 00120 # define FREE_ARRAY(p, count, type) \ 00121 __FREE_ARRAY (p, (count)*(long)sizeof(type), OUR(memory_pool)) 00122 00123 # define POOL_ALLOC(p, type, mempool) \ 00124 __ALLOC_ARRAY (p, (long)sizeof(type), type *, false, mempool) 00125 # define POOL_ALLOC_ARRAY(p, count, type, mempool) \ 00126 __ALLOC_ARRAY (p, (count)*(long)sizeof(type), type *, false, mempool) 00127 # define POOL_TRY_ALLOC_ARRAY(p, count, type, mempool) \ 00128 __ALLOC_ARRAY (p, (count)*(long)sizeof(type), type *, true, mempool) 00129 00130 # define POOL_FREE(p, type, mempool) \ 00131 __FREE_ARRAY (p, (long)sizeof(type), mempool) 00132 # define POOL_FREE_ARRAY(p, count, type, mempool) \ 00133 __FREE_ARRAY (p, (count)*(long)sizeof(type), mempool) 00134 00135 # endif 00136 #endif 00137 00138 00139 00140 #define ZALLOC(_dst_, _type_) do { \ 00141 ALLOC (_dst_, _type_); \ 00142 ZERO_STRUCT (_dst_, _type_); \ 00143 } while (0) 00144 #define ZALLOC_ARRAY(_dst_, _cnt_, _type_) do { \ 00145 ALLOC_ARRAY (_dst_, _cnt_, _type_); \ 00146 ZERO_ARRAY (_dst_, _cnt_, _type_); \ 00147 } while (0) 00148 00149 00150 /* calculates the number that we would need to add to i to get the next multiple of n */ 00151 #define TO_NEXT_MULTIPLE(i,n) (((n)-1) - ((((unsigned POINTER_SIZED_INT)(i))-1)%(n))) 00152 00153 00154 #define ALLOC_ARRAY_ALIGNED(var, count, type, align_in) do { \ 00155 if (align_in <= (1<<ALIGNMENT)) \ 00156 ALLOC_ARRAY(var, count, type); \ 00157 else { \ 00158 unsigned char *_uc_, _offset_; \ 00159 ALLOC_ARRAY(_uc_, (count)*sizeof(type) + align_in, unsigned char);\ 00160 _uc_ += 1; \ 00161 _offset_ = 1 + TO_NEXT_MULTIPLE(_uc_, align_in); \ 00162 _uc_ += _offset_ - 1; \ 00163 _uc_[-1] = _offset_; \ 00164 var = (type *)_uc_; \ 00165 } \ 00166 } while (0) 00167 00168 #define FREE_ARRAY_ALIGNED(var, count, type, align_in) do { \ 00169 if (align_in <= (1<<ALIGNMENT)) \ 00170 FREE_ARRAY(var, count, type); \ 00171 else { \ 00172 unsigned char *_uc_, _offset_; \ 00173 _uc_ = (unsigned char *)var; \ 00174 _offset_ = _uc_[-1]; \ 00175 _uc_ -= _offset_; \ 00176 FREE_ARRAY(_uc_, (count)*sizeof(type)+align_in, unsigned char);\ 00177 } \ 00178 } while (0) 00179 00180 #define ALLOC_ALIGNED(p, type, align_in) ALLOC_ARRAY_ALIGNED(p, 1, type, align_in) 00181 #define FREE_ALIGNED(p, type, align_in) FREE_ARRAY_ALIGNED(p, 1, type, align_in) 00182 00183 /* used to derive a 16-byte aligned address (usually to select a safe address from within a larger buffer) */ 00184 #define ALIGNED_16(x) (((unsigned POINTER_SIZED_INT)(x) + 15) & ~(unsigned POINTER_SIZED_INT)0x00F) 00185 00186 00187 /* 00188 ** creation of a mutex needs memory, normal memory requires a mutex... 00189 ** these macro/wrappers avoid the problem (assuming the underlying 00190 ** memory system is itself thread-safe) 00191 */ 00192 #define ALLOCATE_MEMORY(p,t) \ 00193 (p = (t *)HI_Really_Allocate ((long)sizeof(t), false)) 00194 #define FREE_MEMORY(p,t) \ 00195 HI_Really_Free (p, (long)sizeof(t)) 00196 00197 #define ALLOCATE_MEMORY_ARRAY(p,c,t) (p = (t *)HI_Really_Allocate ((c)*(long)sizeof(t), false)) 00198 #define FREE_MEMORY_ARRAY(p,c,t) HI_Really_Free (p, (c)*(long)sizeof(t)) 00199 00200 00201 #define HOOPS_MEMORY_DEFINED 00202 #endif 00203 00204 00205 00206 00207 00208 00209 00210