svn merge ^/trunk/blender -r41226:41227 .
[blender.git] / source / blender / blenlib / intern / BLI_mempool.c
index b4dc5b7..eb219a3 100644 (file)
@@ -20,7 +20,7 @@
  *
  * The Original Code is: all of this file.
  *
- * Contributor(s): none yet.
+ * Contributor(s): Geoffery Bantle
  *
  * ***** END GPL LICENSE BLOCK *****
  */
 */
 
 #include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+
 #include "BLI_blenlib.h"
+#include "BLI_linklist.h"
 #include "BLI_mempool.h"
-#include <string.h> 
+#include "BLI_utildefines.h"
 
-typedef struct BLI_freenode{
-       struct BLI_freenode *next;
-}BLI_freenode;
+#include "DNA_listBase.h"
+#include "DNA_ID.h"
 
-typedef struct BLI_mempool_chunk{
-       struct BLI_mempool_chunk *next, *prev;
-       void *data;
-}BLI_mempool_chunk;
+#include <string.h> 
 
-typedef struct BLI_mempool{
-       struct ListBase chunks;
-       int esize, csize, pchunk;               /*size of elements and chunks in bytes and number of elements per chunk*/
-       struct BLI_freenode     *free;          /*free element list. Interleaved into chunk datas.*/
-       int totalloc, totused; /*total number of elements allocated in total, and currently in use*/
-       int use_sysmalloc;
-}BLI_mempool;
+#define BLI_MEMPOOL_INTERN
+#include "BLI_mempool.h"
 
-BLI_mempool *BLI_mempool_create(int esize, int tote, int pchunk, int use_sysmalloc)
+BLI_mempool *BLI_mempool_create(int esize, int tote, int pchunk,
+                                                               int use_sysmalloc, int allow_iter)
 {      BLI_mempool  *pool = NULL;
        BLI_freenode *lasttail = NULL, *curnode = NULL;
        int i,j, maxchunks;
        char *addr;
        
-       if (esize < sizeof(void*))
-               esize = sizeof(void*);
+       if (esize < sizeof(void*)*2)
+               esize = sizeof(void*)*2;
        
+       if (esize < sizeof(void*)*2)
+               esize = sizeof(void*)*2;
+
        /*allocate the pool structure*/
        pool = use_sysmalloc ? malloc(sizeof(BLI_mempool)) : MEM_mallocN(sizeof(BLI_mempool), "memory pool");
-       pool->esize = esize;
+       pool->esize = allow_iter ? MAX2(esize, sizeof(BLI_freenode)) : esize;
        pool->use_sysmalloc = use_sysmalloc;
        pool->pchunk = pchunk;  
        pool->csize = esize * pchunk;
        pool->chunks.first = pool->chunks.last = NULL;
        pool->totused= 0;
+       pool->allow_iter= allow_iter;
        
        maxchunks = tote / pchunk + 1;
-       
+       if (maxchunks==0) maxchunks = 1;
+
        /*allocate the actual chunks*/
        for(i=0; i < maxchunks; i++){
                BLI_mempool_chunk *mpchunk = use_sysmalloc ? malloc(sizeof(BLI_mempool_chunk)) : MEM_mallocN(sizeof(BLI_mempool_chunk), "BLI_Mempool Chunk");
@@ -83,30 +84,49 @@ BLI_mempool *BLI_mempool_create(int esize, int tote, int pchunk, int use_sysmall
                mpchunk->data = use_sysmalloc ? malloc(pool->csize) : MEM_mallocN(pool->csize, "BLI Mempool Chunk Data");
                BLI_addtail(&(pool->chunks), mpchunk);
                
-               if(i==0) pool->free = mpchunk->data; /*start of the list*/
+               if(i==0) {
+                       pool->free = mpchunk->data; /*start of the list*/
+                       if (pool->allow_iter)
+                               pool->free->freeword = FREEWORD;
+               }
+
                /*loop through the allocated data, building the pointer structures*/
                for(addr = mpchunk->data, j=0; j < pool->pchunk; j++){
                        curnode = ((BLI_freenode*)addr);
                        addr += pool->esize;
                        curnode->next = (BLI_freenode*)addr;
+                       if (pool->allow_iter) {
+                               if (j != pool->pchunk-1)
+                                       curnode->next->freeword = FREEWORD;
+                               curnode->freeword = FREEWORD;
+                       }
                }
                /*final pointer in the previously allocated chunk is wrong.*/
-               if(lasttail) lasttail->next = mpchunk->data;
+               if(lasttail) {
+                       lasttail->next = mpchunk->data;
+                       if (pool->allow_iter)
+                               lasttail->freeword = FREEWORD;
+               }
+
                /*set the end of this chunks memoryy to the new tail for next iteration*/
                lasttail = curnode;
 
                pool->totalloc += pool->pchunk;
        }
+       
        /*terminate the list*/
        curnode->next = NULL;
        return pool;
 }
+#if 0
 void *BLI_mempool_alloc(BLI_mempool *pool){
        void *retval=NULL;
        BLI_freenode *curnode=NULL;
        char *addr=NULL;
        int j;
-
+       
+       if (!pool) return NULL;
+       
        pool->totused++;
 
        if(!(pool->free)){
@@ -117,10 +137,18 @@ void *BLI_mempool_alloc(BLI_mempool *pool){
                BLI_addtail(&(pool->chunks), mpchunk);
 
                pool->free = mpchunk->data; /*start of the list*/
+               if (pool->allow_iter)
+                       pool->free->freeword = FREEWORD;
                for(addr = mpchunk->data, j=0; j < pool->pchunk; j++){
                        curnode = ((BLI_freenode*)addr);
                        addr += pool->esize;
                        curnode->next = (BLI_freenode*)addr;
+
+                       if (pool->allow_iter) {
+                               curnode->freeword = FREEWORD;
+                               if (j != pool->pchunk-1)
+                                       curnode->next->freeword = FREEWORD;
+                       }
                }
                curnode->next = NULL; /*terminate the list*/
 
@@ -128,15 +156,19 @@ void *BLI_mempool_alloc(BLI_mempool *pool){
        }
 
        retval = pool->free;
+       if (pool->allow_iter)
+               pool->free->freeword = 0x7FFFFFFF;
+
        pool->free = pool->free->next;
        //memset(retval, 0, pool->esize);
        return retval;
 }
+#endif
 
 void *BLI_mempool_calloc(BLI_mempool *pool){
        void *retval=NULL;
        retval = BLI_mempool_alloc(pool);
-       memset(retval, 0, pool->esize);
+       BMEMSET(retval, 0, pool->esize);
        return retval;
 }
 
@@ -146,7 +178,9 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr){ //doesnt protect against d
        BLI_freenode *curnode=NULL;
        char *tmpaddr=NULL;
        int i;
-
+       
+       if (pool->allow_iter)
+               newhead->freeword = FREEWORD;
        newhead->next = pool->free;
        pool->free = newhead;
 
@@ -179,6 +213,50 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr){ //doesnt protect against d
        }
 }
 
+void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter)
+{
+       if (!pool->allow_iter) {
+               fprintf(stderr, "evil! you can't iterate over this mempool!\n");
+               iter->curchunk = NULL;
+               iter->curindex = 0;
+               
+               return;
+       }
+       
+       iter->pool = pool;
+       iter->curchunk = pool->chunks.first;
+       iter->curindex = 0;
+}
+
+static void *bli_mempool_iternext(BLI_mempool_iter *iter)
+{
+       void *ret = NULL;
+       
+       if (!iter->curchunk || !iter->pool->totused) return NULL;
+       
+       ret = ((char*)iter->curchunk->data) + iter->pool->esize*iter->curindex;
+       
+       iter->curindex++;
+       
+       if (iter->curindex >= iter->pool->pchunk) {
+               iter->curchunk = iter->curchunk->next;
+               iter->curindex = 0;
+       }
+       
+       return ret;
+}
+
+void *BLI_mempool_iterstep(BLI_mempool_iter *iter)
+{
+       BLI_freenode *ret;
+       
+       do {
+               ret = bli_mempool_iternext(iter);
+       } while (ret && ret->freeword == FREEWORD);
+       
+       return ret;
+}
+
 void BLI_mempool_destroy(BLI_mempool *pool)
 {
        BLI_mempool_chunk *mpchunk=NULL;