|
Blender
V2.59
|
00001 /* 00002 * 00003 * ***** BEGIN GPL LICENSE BLOCK ***** 00004 * 00005 * This program is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU General Public License 00007 * as published by the Free Software Foundation; either version 2 00008 * of the License, or (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software Foundation, 00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 * 00019 * The Original Code is Copyright (C) 2008 by Blender Foundation. 00020 * All rights reserved. 00021 * 00022 * The Original Code is: all of this file. 00023 * 00024 * Contributor(s): none yet. 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 */ 00028 00034 /* 00035 Simple, fast memory allocator for allocating many elements of the same size. 00036 */ 00037 00038 #include "MEM_guardedalloc.h" 00039 #include "BLI_blenlib.h" 00040 #include "BLI_mempool.h" 00041 #include <string.h> 00042 00043 typedef struct BLI_freenode{ 00044 struct BLI_freenode *next; 00045 }BLI_freenode; 00046 00047 typedef struct BLI_mempool_chunk{ 00048 struct BLI_mempool_chunk *next, *prev; 00049 void *data; 00050 }BLI_mempool_chunk; 00051 00052 typedef struct BLI_mempool{ 00053 struct ListBase chunks; 00054 int esize, csize, pchunk; /*size of elements and chunks in bytes and number of elements per chunk*/ 00055 struct BLI_freenode *free; /*free element list. Interleaved into chunk datas.*/ 00056 int totalloc, totused; /*total number of elements allocated in total, and currently in use*/ 00057 int use_sysmalloc; 00058 }BLI_mempool; 00059 00060 BLI_mempool *BLI_mempool_create(int esize, int tote, int pchunk, int use_sysmalloc) 00061 { BLI_mempool *pool = NULL; 00062 BLI_freenode *lasttail = NULL, *curnode = NULL; 00063 int i,j, maxchunks; 00064 char *addr; 00065 00066 if (esize < sizeof(void*)) 00067 esize = sizeof(void*); 00068 00069 /*allocate the pool structure*/ 00070 pool = use_sysmalloc ? malloc(sizeof(BLI_mempool)) : MEM_mallocN(sizeof(BLI_mempool), "memory pool"); 00071 pool->esize = esize; 00072 pool->use_sysmalloc = use_sysmalloc; 00073 pool->pchunk = pchunk; 00074 pool->csize = esize * pchunk; 00075 pool->chunks.first = pool->chunks.last = NULL; 00076 pool->totused= 0; 00077 00078 maxchunks = tote / pchunk + 1; 00079 00080 /*allocate the actual chunks*/ 00081 for(i=0; i < maxchunks; i++){ 00082 BLI_mempool_chunk *mpchunk = use_sysmalloc ? malloc(sizeof(BLI_mempool_chunk)) : MEM_mallocN(sizeof(BLI_mempool_chunk), "BLI_Mempool Chunk"); 00083 mpchunk->next = mpchunk->prev = NULL; 00084 mpchunk->data = use_sysmalloc ? malloc(pool->csize) : MEM_mallocN(pool->csize, "BLI Mempool Chunk Data"); 00085 BLI_addtail(&(pool->chunks), mpchunk); 00086 00087 if(i==0) pool->free = mpchunk->data; /*start of the list*/ 00088 /*loop through the allocated data, building the pointer structures*/ 00089 for(addr = mpchunk->data, j=0; j < pool->pchunk; j++){ 00090 curnode = ((BLI_freenode*)addr); 00091 addr += pool->esize; 00092 curnode->next = (BLI_freenode*)addr; 00093 } 00094 /*final pointer in the previously allocated chunk is wrong.*/ 00095 if(lasttail) lasttail->next = mpchunk->data; 00096 /*set the end of this chunks memoryy to the new tail for next iteration*/ 00097 lasttail = curnode; 00098 00099 pool->totalloc += pool->pchunk; 00100 } 00101 /*terminate the list*/ 00102 curnode->next = NULL; 00103 return pool; 00104 } 00105 void *BLI_mempool_alloc(BLI_mempool *pool){ 00106 void *retval=NULL; 00107 BLI_freenode *curnode=NULL; 00108 char *addr=NULL; 00109 int j; 00110 00111 pool->totused++; 00112 00113 if(!(pool->free)){ 00114 /*need to allocate a new chunk*/ 00115 BLI_mempool_chunk *mpchunk = pool->use_sysmalloc ? malloc(sizeof(BLI_mempool_chunk)) : MEM_mallocN(sizeof(BLI_mempool_chunk), "BLI_Mempool Chunk"); 00116 mpchunk->next = mpchunk->prev = NULL; 00117 mpchunk->data = pool->use_sysmalloc ? malloc(pool->csize) : MEM_mallocN(pool->csize, "BLI_Mempool Chunk Data"); 00118 BLI_addtail(&(pool->chunks), mpchunk); 00119 00120 pool->free = mpchunk->data; /*start of the list*/ 00121 for(addr = mpchunk->data, j=0; j < pool->pchunk; j++){ 00122 curnode = ((BLI_freenode*)addr); 00123 addr += pool->esize; 00124 curnode->next = (BLI_freenode*)addr; 00125 } 00126 curnode->next = NULL; /*terminate the list*/ 00127 00128 pool->totalloc += pool->pchunk; 00129 } 00130 00131 retval = pool->free; 00132 pool->free = pool->free->next; 00133 //memset(retval, 0, pool->esize); 00134 return retval; 00135 } 00136 00137 void *BLI_mempool_calloc(BLI_mempool *pool){ 00138 void *retval=NULL; 00139 retval = BLI_mempool_alloc(pool); 00140 memset(retval, 0, pool->esize); 00141 return retval; 00142 } 00143 00144 00145 void BLI_mempool_free(BLI_mempool *pool, void *addr){ //doesnt protect against double frees, dont be stupid! 00146 BLI_freenode *newhead = addr; 00147 BLI_freenode *curnode=NULL; 00148 char *tmpaddr=NULL; 00149 int i; 00150 00151 newhead->next = pool->free; 00152 pool->free = newhead; 00153 00154 pool->totused--; 00155 00156 /*nothing is in use; free all the chunks except the first*/ 00157 if (pool->totused == 0) { 00158 BLI_mempool_chunk *mpchunk=NULL, *first; 00159 00160 first = pool->chunks.first; 00161 BLI_remlink(&pool->chunks, first); 00162 00163 for(mpchunk = pool->chunks.first; mpchunk; mpchunk = mpchunk->next) { 00164 if(pool->use_sysmalloc) free(mpchunk->data); 00165 else MEM_freeN(mpchunk->data); 00166 } 00167 00168 pool->use_sysmalloc ? BLI_freelist(&(pool->chunks)) : BLI_freelistN(&(pool->chunks)); 00169 00170 BLI_addtail(&pool->chunks, first); 00171 pool->totalloc = pool->pchunk; 00172 00173 pool->free = first->data; /*start of the list*/ 00174 for(tmpaddr = first->data, i=0; i < pool->pchunk; i++){ 00175 curnode = ((BLI_freenode*)tmpaddr); 00176 tmpaddr += pool->esize; 00177 curnode->next = (BLI_freenode*)tmpaddr; 00178 } 00179 curnode->next = NULL; /*terminate the list*/ 00180 } 00181 } 00182 00183 void BLI_mempool_destroy(BLI_mempool *pool) 00184 { 00185 BLI_mempool_chunk *mpchunk=NULL; 00186 if(pool->use_sysmalloc) { 00187 for(mpchunk = pool->chunks.first; mpchunk; mpchunk = mpchunk->next) { 00188 free(mpchunk->data); 00189 } 00190 BLI_freelist(&(pool->chunks)); 00191 free(pool); 00192 } 00193 else { 00194 for(mpchunk = pool->chunks.first; mpchunk; mpchunk = mpchunk->next) { 00195 MEM_freeN(mpchunk->data); 00196 } 00197 BLI_freelistN(&(pool->chunks)); 00198 MEM_freeN(pool); 00199 } 00200 }