svn merge -r 23207:23528 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[blender.git] / source / blender / blenlib / intern / BLI_mempool.c
1 /**
2  *
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  * The Original Code is Copyright (C) 2008 by Blender Foundation.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 /*
30         Simple, fast memory allocator for allocating many elements of the same size.
31 */
32
33 #include "MEM_guardedalloc.h"
34 #include "BLI_blenlib.h"
35 #include "DNA_listBase.h"
36 #include "BLI_linklist.h"
37 #include <string.h> 
38
39 typedef struct BLI_freenode{
40         struct BLI_freenode *next;
41 }BLI_freenode;
42
43 typedef struct BLI_mempool_chunk{
44         struct BLI_mempool_chunk *next, *prev;
45         void *data;
46 }BLI_mempool_chunk;
47
48 typedef struct BLI_mempool{
49         struct ListBase chunks;
50         int esize, csize, pchunk;               /*size of elements and chunks in bytes and number of elements per chunk*/
51         struct BLI_freenode     *free;          /*free element list. Interleaved into chunk datas.*/
52 }BLI_mempool;
53
54 BLI_mempool *BLI_mempool_create(int esize, int tote, int pchunk)
55 {       BLI_mempool  *pool = NULL;
56         BLI_freenode *lasttail = NULL, *curnode = NULL;
57         int i,j, maxchunks;
58         char *addr;
59         
60         if (esize < sizeof(void*))
61                 esize = sizeof(void*);
62         
63         /*allocate the pool structure*/
64         pool = MEM_mallocN(sizeof(BLI_mempool),"memory pool");
65         pool->esize = esize;
66         pool->pchunk = pchunk;  
67         pool->csize = esize * pchunk;
68         pool->chunks.first = pool->chunks.last = NULL;
69         
70         maxchunks = tote / pchunk;
71         
72         /*allocate the actual chunks*/
73         for(i=0; i < maxchunks; i++){
74                 BLI_mempool_chunk *mpchunk = MEM_mallocN(sizeof(BLI_mempool_chunk), "BLI_Mempool Chunk");
75                 mpchunk->next = mpchunk->prev = NULL;
76                 mpchunk->data = MEM_mallocN(pool->csize, "BLI Mempool Chunk Data");
77                 BLI_addtail(&(pool->chunks), mpchunk);
78                 
79                 if(i==0) pool->free = mpchunk->data; /*start of the list*/
80                 /*loop through the allocated data, building the pointer structures*/
81                 for(addr = mpchunk->data, j=0; j < pool->pchunk; j++){
82                         curnode = ((BLI_freenode*)addr);
83                         addr += pool->esize;
84                         curnode->next = (BLI_freenode*)addr;
85                 }
86                 /*final pointer in the previously allocated chunk is wrong.*/
87                 if(lasttail) lasttail->next = mpchunk->data;
88                 /*set the end of this chunks memoryy to the new tail for next iteration*/
89                 lasttail = curnode;
90         }
91         /*terminate the list*/
92         curnode->next = NULL;
93         return pool;
94 }
95 void *BLI_mempool_alloc(BLI_mempool *pool){
96         void *retval=NULL;
97         BLI_freenode *curnode=NULL;
98         char *addr=NULL;
99         int j;
100
101         if(!(pool->free)){
102                 /*need to allocate a new chunk*/
103                 BLI_mempool_chunk *mpchunk = MEM_mallocN(sizeof(BLI_mempool_chunk), "BLI_Mempool Chunk");
104                 mpchunk->next = mpchunk->prev = NULL;
105                 mpchunk->data = MEM_mallocN(pool->csize, "BLI_Mempool Chunk Data");
106                 BLI_addtail(&(pool->chunks), mpchunk);
107
108                 pool->free = mpchunk->data; /*start of the list*/
109                 for(addr = mpchunk->data, j=0; j < pool->pchunk; j++){
110                         curnode = ((BLI_freenode*)addr);
111                         addr += pool->esize;
112                         curnode->next = (BLI_freenode*)addr;
113                 }
114                 curnode->next = NULL; /*terminate the list*/
115         }
116
117         retval = pool->free;
118         pool->free = pool->free->next;
119         //memset(retval, 0, pool->esize);
120         return retval;
121 }
122
123 void *BLI_mempool_calloc(BLI_mempool *pool){
124         void *retval=NULL;
125         retval = BLI_mempool_alloc(pool);
126         memset(retval, 0, pool->esize);
127         return retval;
128 }
129
130
131
132 void BLI_mempool_free(BLI_mempool *pool, void *addr){ //doesnt protect against double frees, dont be stupid!
133         BLI_freenode *newhead = addr;
134         newhead->next = pool->free;
135         pool->free = newhead;
136 }
137 void BLI_mempool_destroy(BLI_mempool *pool)
138 {
139         BLI_mempool_chunk *mpchunk=NULL;
140         for(mpchunk = pool->chunks.first; mpchunk; mpchunk = mpchunk->next) MEM_freeN(mpchunk->data);
141         BLI_freelistN(&(pool->chunks));
142         MEM_freeN(pool);
143 }