2011-02-23 10:52:22 +00:00
|
|
|
/*
|
2008-07-04 17:32:55 +00:00
|
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
2010-02-12 13:34:04 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2008-07-04 17:32:55 +00:00
|
|
|
*
|
|
|
|
|
* The Original Code is Copyright (C) 2008 by Blender Foundation.
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* The Original Code is: all of this file.
|
|
|
|
|
*
|
2011-11-16 19:31:42 +00:00
|
|
|
* Contributor(s): Geoffery Bantle
|
2008-07-04 17:32:55 +00:00
|
|
|
*
|
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
|
*/
|
|
|
|
|
|
2011-02-27 20:37:56 +00:00
|
|
|
/** \file blender/blenlib/intern/BLI_mempool.c
|
|
|
|
|
* \ingroup bli
|
|
|
|
|
*/
|
|
|
|
|
|
2008-07-04 17:32:55 +00:00
|
|
|
/*
|
2011-11-16 19:31:42 +00:00
|
|
|
* Simple, fast memory allocator for allocating many elements of the same size.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "BLI_utildefines.h"
|
|
|
|
|
#include "BLI_listbase.h"
|
|
|
|
|
|
|
|
|
|
#include "BLI_mempool.h" /* own include */
|
|
|
|
|
|
|
|
|
|
#include "DNA_listBase.h"
|
2008-07-04 17:32:55 +00:00
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
2011-11-16 19:31:42 +00:00
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
|
|
/* note: copied from BKE_utildefines.h, dont use here because we're in BLI */
|
|
|
|
|
#ifdef __BIG_ENDIAN__
|
|
|
|
|
/* Big Endian */
|
|
|
|
|
# define MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) )
|
|
|
|
|
#else
|
|
|
|
|
/* Little Endian */
|
|
|
|
|
# define MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#define FREEWORD MAKE_ID('f', 'r', 'e', 'e')
|
2008-07-04 17:32:55 +00:00
|
|
|
|
2011-11-16 16:50:30 +00:00
|
|
|
typedef struct BLI_freenode {
|
2008-07-04 17:32:55 +00:00
|
|
|
struct BLI_freenode *next;
|
2011-11-16 19:31:42 +00:00
|
|
|
int freeword; /* used to identify this as a freed node */
|
2011-11-16 16:50:30 +00:00
|
|
|
} BLI_freenode;
|
2008-07-04 17:32:55 +00:00
|
|
|
|
2011-11-16 16:50:30 +00:00
|
|
|
typedef struct BLI_mempool_chunk {
|
2008-07-04 17:32:55 +00:00
|
|
|
struct BLI_mempool_chunk *next, *prev;
|
|
|
|
|
void *data;
|
2011-11-16 16:50:30 +00:00
|
|
|
} BLI_mempool_chunk;
|
2008-07-04 17:32:55 +00:00
|
|
|
|
2011-11-16 22:20:17 +00:00
|
|
|
struct BLI_mempool {
|
2008-07-04 17:32:55 +00:00
|
|
|
struct ListBase chunks;
|
2011-11-27 01:20:08 +00:00
|
|
|
int esize; /* element size in bytes */
|
|
|
|
|
int csize; /* chunk size in bytes */
|
|
|
|
|
int pchunk; /* number of elements per chunk */
|
2012-03-01 22:59:18 +00:00
|
|
|
int flag;
|
2011-11-16 19:31:42 +00:00
|
|
|
/* keeps aligned to 16 bits */
|
|
|
|
|
|
2012-03-11 23:47:41 +00:00
|
|
|
BLI_freenode *free; /* free element list. Interleaved into chunk datas. */
|
2012-03-01 23:14:51 +00:00
|
|
|
int totalloc, totused; /* total number of elements allocated in total,
|
|
|
|
|
* and currently in use */
|
2011-11-16 22:20:17 +00:00
|
|
|
};
|
2008-07-04 17:32:55 +00:00
|
|
|
|
2011-11-16 19:31:42 +00:00
|
|
|
#define MEMPOOL_ELEM_SIZE_MIN (sizeof(void *) * 2)
|
|
|
|
|
|
2012-03-01 23:14:51 +00:00
|
|
|
BLI_mempool *BLI_mempool_create(int esize, int totelem, int pchunk, int flag)
|
2011-11-16 16:50:30 +00:00
|
|
|
{
|
2012-03-11 23:47:41 +00:00
|
|
|
BLI_mempool *pool = NULL;
|
2008-07-04 17:32:55 +00:00
|
|
|
BLI_freenode *lasttail = NULL, *curnode = NULL;
|
2012-03-11 23:47:41 +00:00
|
|
|
int i, j, maxchunks;
|
2008-07-04 17:32:55 +00:00
|
|
|
char *addr;
|
2011-11-16 19:31:42 +00:00
|
|
|
|
2012-03-01 23:14:51 +00:00
|
|
|
/* allocate the pool structure */
|
|
|
|
|
if (flag & BLI_MEMPOOL_SYSMALLOC) {
|
|
|
|
|
pool = malloc(sizeof(BLI_mempool));
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
pool = MEM_mallocN(sizeof(BLI_mempool), "memory pool");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* set the elem size */
|
|
|
|
|
if (esize < MEMPOOL_ELEM_SIZE_MIN) {
|
2011-11-16 19:31:42 +00:00
|
|
|
esize = MEMPOOL_ELEM_SIZE_MIN;
|
2012-03-01 23:14:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (flag & BLI_MEMPOOL_ALLOW_ITER) {
|
|
|
|
|
pool->esize = MAX2(esize, sizeof(BLI_freenode));
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
pool->esize = esize;
|
|
|
|
|
}
|
2011-11-16 19:31:42 +00:00
|
|
|
|
2012-03-01 22:59:18 +00:00
|
|
|
pool->flag = flag;
|
2011-11-16 16:50:30 +00:00
|
|
|
pool->pchunk = pchunk;
|
2008-07-04 17:32:55 +00:00
|
|
|
pool->csize = esize * pchunk;
|
|
|
|
|
pool->chunks.first = pool->chunks.last = NULL;
|
2012-03-01 23:14:51 +00:00
|
|
|
pool->totused = 0;
|
2012-03-11 23:47:41 +00:00
|
|
|
|
2012-03-01 23:14:51 +00:00
|
|
|
maxchunks = totelem / pchunk + 1;
|
|
|
|
|
if (maxchunks == 0) {
|
|
|
|
|
maxchunks = 1;
|
|
|
|
|
}
|
2011-11-16 19:31:42 +00:00
|
|
|
|
2012-03-01 22:59:18 +00:00
|
|
|
/* allocate the actual chunks */
|
|
|
|
|
for (i = 0; i < maxchunks; i++) {
|
|
|
|
|
BLI_mempool_chunk *mpchunk;
|
|
|
|
|
|
|
|
|
|
if (flag & BLI_MEMPOOL_SYSMALLOC) {
|
2012-03-11 23:47:41 +00:00
|
|
|
mpchunk = malloc(sizeof(BLI_mempool_chunk));
|
2012-03-01 22:59:18 +00:00
|
|
|
mpchunk->data = malloc(pool->csize);
|
|
|
|
|
}
|
|
|
|
|
else {
|
2012-03-11 23:47:41 +00:00
|
|
|
mpchunk = MEM_mallocN(sizeof(BLI_mempool_chunk), "BLI_Mempool Chunk");
|
2012-03-01 22:59:18 +00:00
|
|
|
mpchunk->data = MEM_mallocN(pool->csize, "BLI Mempool Chunk Data");
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-04 17:32:55 +00:00
|
|
|
mpchunk->next = mpchunk->prev = NULL;
|
|
|
|
|
BLI_addtail(&(pool->chunks), mpchunk);
|
2012-03-11 23:47:41 +00:00
|
|
|
|
2012-03-01 23:14:51 +00:00
|
|
|
if (i == 0) {
|
|
|
|
|
pool->free = mpchunk->data; /* start of the list */
|
2012-03-01 22:59:18 +00:00
|
|
|
if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) {
|
2011-11-16 19:31:42 +00:00
|
|
|
pool->free->freeword = FREEWORD;
|
2012-03-01 22:59:18 +00:00
|
|
|
}
|
2011-11-16 19:31:42 +00:00
|
|
|
}
|
|
|
|
|
|
2012-03-01 23:14:51 +00:00
|
|
|
/* loop through the allocated data, building the pointer structures */
|
|
|
|
|
for (addr = mpchunk->data, j = 0; j < pool->pchunk; j++) {
|
|
|
|
|
curnode = ((BLI_freenode *)addr);
|
2008-07-04 17:32:55 +00:00
|
|
|
addr += pool->esize;
|
2012-03-01 23:14:51 +00:00
|
|
|
curnode->next = (BLI_freenode *)addr;
|
2012-03-01 22:59:18 +00:00
|
|
|
if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) {
|
2012-03-01 23:14:51 +00:00
|
|
|
if (j != pool->pchunk - 1)
|
2011-11-16 19:31:42 +00:00
|
|
|
curnode->next->freeword = FREEWORD;
|
|
|
|
|
curnode->freeword = FREEWORD;
|
|
|
|
|
}
|
2008-07-04 17:32:55 +00:00
|
|
|
}
|
2012-03-01 23:14:51 +00:00
|
|
|
/* final pointer in the previously allocated chunk is wrong */
|
2011-11-16 19:31:42 +00:00
|
|
|
if (lasttail) {
|
|
|
|
|
lasttail->next = mpchunk->data;
|
2012-03-01 22:59:18 +00:00
|
|
|
if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) {
|
2011-11-16 19:31:42 +00:00
|
|
|
lasttail->freeword = FREEWORD;
|
2012-03-01 22:59:18 +00:00
|
|
|
}
|
2011-11-16 19:31:42 +00:00
|
|
|
}
|
|
|
|
|
|
2012-03-01 23:14:51 +00:00
|
|
|
/* set the end of this chunks memoryy to the new tail for next iteration */
|
2008-07-04 17:32:55 +00:00
|
|
|
lasttail = curnode;
|
Added a new notifyer, NC_SPACE_CHANGED, to signal an editor that
replaces another so it can do updates (e.g. dopesheet editor can
sync channel selection).
Also coded a simple optimization for allocating small objects,
based on mempools. It's #ifdef'd out, you can enabled it by
defining OPTIMIZE_SMALL_BLOCKS (e.g. adding -DDOPTIMIZE_SMALL_BLOCKS to
your compiler flags).
We suffer from a great deal of performance loss from the system allocator
(vgroups, ghash, edgehash, the singly-linked list implementation in blenlib,
editmesh, and likely a great many areas I'm forgetting), and this is the
common solution for handling the many-small-objects problem. It's not
really production-ready yet (it's long-term memory consequencers need to
be profiled first, and the implementation tweaked as necassary), but for
people on systems with slow system allocators it's worth trying.
Note that since this creates a guardedalloc<->blenlib link, the build systems
need to be updated accordingly (I've already done this for scons, though I'm
not sure if the player builds).
2010-01-21 03:08:57 +00:00
|
|
|
|
|
|
|
|
pool->totalloc += pool->pchunk;
|
2008-07-04 17:32:55 +00:00
|
|
|
}
|
2012-03-01 23:14:51 +00:00
|
|
|
/* terminate the list */
|
2008-07-04 17:32:55 +00:00
|
|
|
curnode->next = NULL;
|
|
|
|
|
return pool;
|
|
|
|
|
}
|
2011-11-16 16:50:30 +00:00
|
|
|
|
|
|
|
|
void *BLI_mempool_alloc(BLI_mempool *pool)
|
|
|
|
|
{
|
2012-03-01 23:14:51 +00:00
|
|
|
void *retval = NULL;
|
2008-07-04 17:32:55 +00:00
|
|
|
|
Added a new notifyer, NC_SPACE_CHANGED, to signal an editor that
replaces another so it can do updates (e.g. dopesheet editor can
sync channel selection).
Also coded a simple optimization for allocating small objects,
based on mempools. It's #ifdef'd out, you can enabled it by
defining OPTIMIZE_SMALL_BLOCKS (e.g. adding -DDOPTIMIZE_SMALL_BLOCKS to
your compiler flags).
We suffer from a great deal of performance loss from the system allocator
(vgroups, ghash, edgehash, the singly-linked list implementation in blenlib,
editmesh, and likely a great many areas I'm forgetting), and this is the
common solution for handling the many-small-objects problem. It's not
really production-ready yet (it's long-term memory consequencers need to
be profiled first, and the implementation tweaked as necassary), but for
people on systems with slow system allocators it's worth trying.
Note that since this creates a guardedalloc<->blenlib link, the build systems
need to be updated accordingly (I've already done this for scons, though I'm
not sure if the player builds).
2010-01-21 03:08:57 +00:00
|
|
|
pool->totused++;
|
|
|
|
|
|
2011-11-16 16:50:30 +00:00
|
|
|
if (!(pool->free)) {
|
2012-03-01 23:14:51 +00:00
|
|
|
BLI_freenode *curnode = NULL;
|
2011-11-16 16:50:30 +00:00
|
|
|
char *addr;
|
|
|
|
|
int j;
|
|
|
|
|
|
2012-03-01 23:14:51 +00:00
|
|
|
/* need to allocate a new chunk */
|
2012-03-01 22:59:18 +00:00
|
|
|
BLI_mempool_chunk *mpchunk;
|
|
|
|
|
|
|
|
|
|
if (pool->flag & BLI_MEMPOOL_SYSMALLOC) {
|
|
|
|
|
mpchunk = malloc(sizeof(BLI_mempool_chunk));
|
|
|
|
|
mpchunk->data = malloc(pool->csize);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
mpchunk = MEM_mallocN(sizeof(BLI_mempool_chunk), "BLI_Mempool Chunk");
|
|
|
|
|
mpchunk->data = MEM_mallocN(pool->csize, "BLI_Mempool Chunk Data");
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-04 17:32:55 +00:00
|
|
|
mpchunk->next = mpchunk->prev = NULL;
|
|
|
|
|
BLI_addtail(&(pool->chunks), mpchunk);
|
|
|
|
|
|
2012-03-01 22:59:18 +00:00
|
|
|
pool->free = mpchunk->data; /* start of the list */
|
|
|
|
|
|
|
|
|
|
if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) {
|
2011-11-16 19:31:42 +00:00
|
|
|
pool->free->freeword = FREEWORD;
|
2012-03-01 22:59:18 +00:00
|
|
|
}
|
|
|
|
|
|
2012-03-01 23:14:51 +00:00
|
|
|
for (addr = mpchunk->data, j = 0; j < pool->pchunk; j++) {
|
|
|
|
|
curnode = ((BLI_freenode *)addr);
|
2008-07-04 17:32:55 +00:00
|
|
|
addr += pool->esize;
|
2012-03-01 23:14:51 +00:00
|
|
|
curnode->next = (BLI_freenode *)addr;
|
2011-11-16 19:31:42 +00:00
|
|
|
|
2012-03-01 22:59:18 +00:00
|
|
|
if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) {
|
2011-11-16 19:31:42 +00:00
|
|
|
curnode->freeword = FREEWORD;
|
2012-03-01 23:14:51 +00:00
|
|
|
if (j != pool->pchunk - 1)
|
2011-11-16 19:31:42 +00:00
|
|
|
curnode->next->freeword = FREEWORD;
|
|
|
|
|
}
|
2008-07-04 17:32:55 +00:00
|
|
|
}
|
2012-03-01 23:14:51 +00:00
|
|
|
curnode->next = NULL; /* terminate the list */
|
Added a new notifyer, NC_SPACE_CHANGED, to signal an editor that
replaces another so it can do updates (e.g. dopesheet editor can
sync channel selection).
Also coded a simple optimization for allocating small objects,
based on mempools. It's #ifdef'd out, you can enabled it by
defining OPTIMIZE_SMALL_BLOCKS (e.g. adding -DDOPTIMIZE_SMALL_BLOCKS to
your compiler flags).
We suffer from a great deal of performance loss from the system allocator
(vgroups, ghash, edgehash, the singly-linked list implementation in blenlib,
editmesh, and likely a great many areas I'm forgetting), and this is the
common solution for handling the many-small-objects problem. It's not
really production-ready yet (it's long-term memory consequencers need to
be profiled first, and the implementation tweaked as necassary), but for
people on systems with slow system allocators it's worth trying.
Note that since this creates a guardedalloc<->blenlib link, the build systems
need to be updated accordingly (I've already done this for scons, though I'm
not sure if the player builds).
2010-01-21 03:08:57 +00:00
|
|
|
|
|
|
|
|
pool->totalloc += pool->pchunk;
|
2008-07-04 17:32:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
retval = pool->free;
|
2012-03-01 22:59:18 +00:00
|
|
|
|
|
|
|
|
if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) {
|
2011-11-16 19:31:42 +00:00
|
|
|
pool->free->freeword = 0x7FFFFFFF;
|
2012-03-01 22:59:18 +00:00
|
|
|
}
|
2011-11-16 19:31:42 +00:00
|
|
|
|
2008-07-04 17:32:55 +00:00
|
|
|
pool->free = pool->free->next;
|
|
|
|
|
//memset(retval, 0, pool->esize);
|
|
|
|
|
return retval;
|
|
|
|
|
}
|
2008-07-08 02:22:37 +00:00
|
|
|
|
2011-11-16 16:50:30 +00:00
|
|
|
void *BLI_mempool_calloc(BLI_mempool *pool)
|
|
|
|
|
{
|
2012-03-01 23:14:51 +00:00
|
|
|
void *retval = BLI_mempool_alloc(pool);
|
2008-07-08 02:22:37 +00:00
|
|
|
memset(retval, 0, pool->esize);
|
|
|
|
|
return retval;
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-16 16:50:30 +00:00
|
|
|
/* doesnt protect against double frees, dont be stupid! */
|
|
|
|
|
void BLI_mempool_free(BLI_mempool *pool, void *addr)
|
|
|
|
|
{
|
2008-07-04 17:32:55 +00:00
|
|
|
BLI_freenode *newhead = addr;
|
Added a new notifyer, NC_SPACE_CHANGED, to signal an editor that
replaces another so it can do updates (e.g. dopesheet editor can
sync channel selection).
Also coded a simple optimization for allocating small objects,
based on mempools. It's #ifdef'd out, you can enabled it by
defining OPTIMIZE_SMALL_BLOCKS (e.g. adding -DDOPTIMIZE_SMALL_BLOCKS to
your compiler flags).
We suffer from a great deal of performance loss from the system allocator
(vgroups, ghash, edgehash, the singly-linked list implementation in blenlib,
editmesh, and likely a great many areas I'm forgetting), and this is the
common solution for handling the many-small-objects problem. It's not
really production-ready yet (it's long-term memory consequencers need to
be profiled first, and the implementation tweaked as necassary), but for
people on systems with slow system allocators it's worth trying.
Note that since this creates a guardedalloc<->blenlib link, the build systems
need to be updated accordingly (I've already done this for scons, though I'm
not sure if the player builds).
2010-01-21 03:08:57 +00:00
|
|
|
|
2012-03-01 22:59:18 +00:00
|
|
|
if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) {
|
2011-11-16 19:31:42 +00:00
|
|
|
newhead->freeword = FREEWORD;
|
2012-03-01 22:59:18 +00:00
|
|
|
}
|
|
|
|
|
|
2008-07-04 17:32:55 +00:00
|
|
|
newhead->next = pool->free;
|
|
|
|
|
pool->free = newhead;
|
Added a new notifyer, NC_SPACE_CHANGED, to signal an editor that
replaces another so it can do updates (e.g. dopesheet editor can
sync channel selection).
Also coded a simple optimization for allocating small objects,
based on mempools. It's #ifdef'd out, you can enabled it by
defining OPTIMIZE_SMALL_BLOCKS (e.g. adding -DDOPTIMIZE_SMALL_BLOCKS to
your compiler flags).
We suffer from a great deal of performance loss from the system allocator
(vgroups, ghash, edgehash, the singly-linked list implementation in blenlib,
editmesh, and likely a great many areas I'm forgetting), and this is the
common solution for handling the many-small-objects problem. It's not
really production-ready yet (it's long-term memory consequencers need to
be profiled first, and the implementation tweaked as necassary), but for
people on systems with slow system allocators it's worth trying.
Note that since this creates a guardedalloc<->blenlib link, the build systems
need to be updated accordingly (I've already done this for scons, though I'm
not sure if the player builds).
2010-01-21 03:08:57 +00:00
|
|
|
|
|
|
|
|
pool->totused--;
|
|
|
|
|
|
2012-03-01 23:14:51 +00:00
|
|
|
/* nothing is in use; free all the chunks except the first */
|
Added a new notifyer, NC_SPACE_CHANGED, to signal an editor that
replaces another so it can do updates (e.g. dopesheet editor can
sync channel selection).
Also coded a simple optimization for allocating small objects,
based on mempools. It's #ifdef'd out, you can enabled it by
defining OPTIMIZE_SMALL_BLOCKS (e.g. adding -DDOPTIMIZE_SMALL_BLOCKS to
your compiler flags).
We suffer from a great deal of performance loss from the system allocator
(vgroups, ghash, edgehash, the singly-linked list implementation in blenlib,
editmesh, and likely a great many areas I'm forgetting), and this is the
common solution for handling the many-small-objects problem. It's not
really production-ready yet (it's long-term memory consequencers need to
be profiled first, and the implementation tweaked as necassary), but for
people on systems with slow system allocators it's worth trying.
Note that since this creates a guardedalloc<->blenlib link, the build systems
need to be updated accordingly (I've already done this for scons, though I'm
not sure if the player builds).
2010-01-21 03:08:57 +00:00
|
|
|
if (pool->totused == 0) {
|
2012-03-01 23:14:51 +00:00
|
|
|
BLI_freenode *curnode = NULL;
|
|
|
|
|
char *tmpaddr = NULL;
|
2011-11-16 16:50:30 +00:00
|
|
|
int i;
|
|
|
|
|
|
2012-03-01 23:14:51 +00:00
|
|
|
BLI_mempool_chunk *mpchunk = NULL;
|
|
|
|
|
BLI_mempool_chunk *first = pool->chunks.first;
|
Added a new notifyer, NC_SPACE_CHANGED, to signal an editor that
replaces another so it can do updates (e.g. dopesheet editor can
sync channel selection).
Also coded a simple optimization for allocating small objects,
based on mempools. It's #ifdef'd out, you can enabled it by
defining OPTIMIZE_SMALL_BLOCKS (e.g. adding -DDOPTIMIZE_SMALL_BLOCKS to
your compiler flags).
We suffer from a great deal of performance loss from the system allocator
(vgroups, ghash, edgehash, the singly-linked list implementation in blenlib,
editmesh, and likely a great many areas I'm forgetting), and this is the
common solution for handling the many-small-objects problem. It's not
really production-ready yet (it's long-term memory consequencers need to
be profiled first, and the implementation tweaked as necassary), but for
people on systems with slow system allocators it's worth trying.
Note that since this creates a guardedalloc<->blenlib link, the build systems
need to be updated accordingly (I've already done this for scons, though I'm
not sure if the player builds).
2010-01-21 03:08:57 +00:00
|
|
|
|
|
|
|
|
BLI_remlink(&pool->chunks, first);
|
|
|
|
|
|
2012-03-01 22:59:18 +00:00
|
|
|
if (pool->flag & BLI_MEMPOOL_SYSMALLOC) {
|
|
|
|
|
for (mpchunk = pool->chunks.first; mpchunk; mpchunk = mpchunk->next) {
|
|
|
|
|
free(mpchunk->data);
|
|
|
|
|
}
|
|
|
|
|
BLI_freelist(&(pool->chunks));
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
for (mpchunk = pool->chunks.first; mpchunk; mpchunk = mpchunk->next) {
|
|
|
|
|
MEM_freeN(mpchunk->data);
|
|
|
|
|
}
|
|
|
|
|
BLI_freelistN(&(pool->chunks));
|
2010-10-30 17:16:37 +00:00
|
|
|
}
|
|
|
|
|
|
Added a new notifyer, NC_SPACE_CHANGED, to signal an editor that
replaces another so it can do updates (e.g. dopesheet editor can
sync channel selection).
Also coded a simple optimization for allocating small objects,
based on mempools. It's #ifdef'd out, you can enabled it by
defining OPTIMIZE_SMALL_BLOCKS (e.g. adding -DDOPTIMIZE_SMALL_BLOCKS to
your compiler flags).
We suffer from a great deal of performance loss from the system allocator
(vgroups, ghash, edgehash, the singly-linked list implementation in blenlib,
editmesh, and likely a great many areas I'm forgetting), and this is the
common solution for handling the many-small-objects problem. It's not
really production-ready yet (it's long-term memory consequencers need to
be profiled first, and the implementation tweaked as necassary), but for
people on systems with slow system allocators it's worth trying.
Note that since this creates a guardedalloc<->blenlib link, the build systems
need to be updated accordingly (I've already done this for scons, though I'm
not sure if the player builds).
2010-01-21 03:08:57 +00:00
|
|
|
BLI_addtail(&pool->chunks, first);
|
|
|
|
|
pool->totalloc = pool->pchunk;
|
|
|
|
|
|
2012-03-01 23:14:51 +00:00
|
|
|
pool->free = first->data; /* start of the list */
|
|
|
|
|
for (tmpaddr = first->data, i = 0; i < pool->pchunk; i++) {
|
|
|
|
|
curnode = ((BLI_freenode *)tmpaddr);
|
Added a new notifyer, NC_SPACE_CHANGED, to signal an editor that
replaces another so it can do updates (e.g. dopesheet editor can
sync channel selection).
Also coded a simple optimization for allocating small objects,
based on mempools. It's #ifdef'd out, you can enabled it by
defining OPTIMIZE_SMALL_BLOCKS (e.g. adding -DDOPTIMIZE_SMALL_BLOCKS to
your compiler flags).
We suffer from a great deal of performance loss from the system allocator
(vgroups, ghash, edgehash, the singly-linked list implementation in blenlib,
editmesh, and likely a great many areas I'm forgetting), and this is the
common solution for handling the many-small-objects problem. It's not
really production-ready yet (it's long-term memory consequencers need to
be profiled first, and the implementation tweaked as necassary), but for
people on systems with slow system allocators it's worth trying.
Note that since this creates a guardedalloc<->blenlib link, the build systems
need to be updated accordingly (I've already done this for scons, though I'm
not sure if the player builds).
2010-01-21 03:08:57 +00:00
|
|
|
tmpaddr += pool->esize;
|
2012-03-01 23:14:51 +00:00
|
|
|
curnode->next = (BLI_freenode *)tmpaddr;
|
Added a new notifyer, NC_SPACE_CHANGED, to signal an editor that
replaces another so it can do updates (e.g. dopesheet editor can
sync channel selection).
Also coded a simple optimization for allocating small objects,
based on mempools. It's #ifdef'd out, you can enabled it by
defining OPTIMIZE_SMALL_BLOCKS (e.g. adding -DDOPTIMIZE_SMALL_BLOCKS to
your compiler flags).
We suffer from a great deal of performance loss from the system allocator
(vgroups, ghash, edgehash, the singly-linked list implementation in blenlib,
editmesh, and likely a great many areas I'm forgetting), and this is the
common solution for handling the many-small-objects problem. It's not
really production-ready yet (it's long-term memory consequencers need to
be profiled first, and the implementation tweaked as necassary), but for
people on systems with slow system allocators it's worth trying.
Note that since this creates a guardedalloc<->blenlib link, the build systems
need to be updated accordingly (I've already done this for scons, though I'm
not sure if the player builds).
2010-01-21 03:08:57 +00:00
|
|
|
}
|
2012-03-01 23:14:51 +00:00
|
|
|
curnode->next = NULL; /* terminate the list */
|
Added a new notifyer, NC_SPACE_CHANGED, to signal an editor that
replaces another so it can do updates (e.g. dopesheet editor can
sync channel selection).
Also coded a simple optimization for allocating small objects,
based on mempools. It's #ifdef'd out, you can enabled it by
defining OPTIMIZE_SMALL_BLOCKS (e.g. adding -DDOPTIMIZE_SMALL_BLOCKS to
your compiler flags).
We suffer from a great deal of performance loss from the system allocator
(vgroups, ghash, edgehash, the singly-linked list implementation in blenlib,
editmesh, and likely a great many areas I'm forgetting), and this is the
common solution for handling the many-small-objects problem. It's not
really production-ready yet (it's long-term memory consequencers need to
be profiled first, and the implementation tweaked as necassary), but for
people on systems with slow system allocators it's worth trying.
Note that since this creates a guardedalloc<->blenlib link, the build systems
need to be updated accordingly (I've already done this for scons, though I'm
not sure if the player builds).
2010-01-21 03:08:57 +00:00
|
|
|
}
|
2008-07-04 17:32:55 +00:00
|
|
|
}
|
Added a new notifyer, NC_SPACE_CHANGED, to signal an editor that
replaces another so it can do updates (e.g. dopesheet editor can
sync channel selection).
Also coded a simple optimization for allocating small objects,
based on mempools. It's #ifdef'd out, you can enabled it by
defining OPTIMIZE_SMALL_BLOCKS (e.g. adding -DDOPTIMIZE_SMALL_BLOCKS to
your compiler flags).
We suffer from a great deal of performance loss from the system allocator
(vgroups, ghash, edgehash, the singly-linked list implementation in blenlib,
editmesh, and likely a great many areas I'm forgetting), and this is the
common solution for handling the many-small-objects problem. It's not
really production-ready yet (it's long-term memory consequencers need to
be profiled first, and the implementation tweaked as necassary), but for
people on systems with slow system allocators it's worth trying.
Note that since this creates a guardedalloc<->blenlib link, the build systems
need to be updated accordingly (I've already done this for scons, though I'm
not sure if the player builds).
2010-01-21 03:08:57 +00:00
|
|
|
|
2012-02-29 15:00:37 +00:00
|
|
|
int BLI_mempool_count(BLI_mempool *pool)
|
|
|
|
|
{
|
|
|
|
|
return pool->totused;
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-27 21:11:17 +00:00
|
|
|
void *BLI_mempool_findelem(BLI_mempool *pool, int index)
|
2011-11-27 01:20:08 +00:00
|
|
|
{
|
2012-03-01 22:59:18 +00:00
|
|
|
if (!(pool->flag & BLI_MEMPOOL_ALLOW_ITER)) {
|
2011-11-27 21:11:17 +00:00
|
|
|
fprintf(stderr, "%s: Error! you can't iterate over this mempool!\n", __func__);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
else if ((index >= 0) && (index < pool->totused)) {
|
|
|
|
|
/* we could have some faster mem chunk stepping code inline */
|
|
|
|
|
BLI_mempool_iter iter;
|
|
|
|
|
void *elem;
|
|
|
|
|
BLI_mempool_iternew(pool, &iter);
|
2012-03-11 23:47:41 +00:00
|
|
|
for (elem = BLI_mempool_iterstep(&iter); index-- != 0; elem = BLI_mempool_iterstep(&iter)) {
|
|
|
|
|
/* do nothing */
|
|
|
|
|
};
|
2011-11-27 21:11:17 +00:00
|
|
|
return elem;
|
2011-11-27 01:20:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-16 19:31:42 +00:00
|
|
|
void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter)
|
|
|
|
|
{
|
2012-03-01 22:59:18 +00:00
|
|
|
if (!(pool->flag & BLI_MEMPOOL_ALLOW_ITER)) {
|
2011-11-16 19:31:42 +00:00
|
|
|
fprintf(stderr, "%s: Error! you can't iterate over this mempool!\n", __func__);
|
|
|
|
|
iter->curchunk = NULL;
|
|
|
|
|
iter->curindex = 0;
|
2012-03-11 23:47:41 +00:00
|
|
|
|
2011-11-16 19:31:42 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2012-03-11 23:47:41 +00:00
|
|
|
|
2011-11-16 19:31:42 +00:00
|
|
|
iter->pool = pool;
|
|
|
|
|
iter->curchunk = pool->chunks.first;
|
|
|
|
|
iter->curindex = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-29 03:39:59 +00:00
|
|
|
#if 0
|
|
|
|
|
/* unoptimized, more readable */
|
|
|
|
|
|
2011-11-16 19:31:42 +00:00
|
|
|
static void *bli_mempool_iternext(BLI_mempool_iter *iter)
|
|
|
|
|
{
|
|
|
|
|
void *ret = NULL;
|
2012-03-11 23:47:41 +00:00
|
|
|
|
2011-11-16 19:31:42 +00:00
|
|
|
if (!iter->curchunk || !iter->pool->totused) return NULL;
|
2012-03-11 23:47:41 +00:00
|
|
|
|
2012-03-01 23:14:51 +00:00
|
|
|
ret = ((char *)iter->curchunk->data) + iter->pool->esize * iter->curindex;
|
2012-03-11 23:47:41 +00:00
|
|
|
|
2011-11-16 19:31:42 +00:00
|
|
|
iter->curindex++;
|
2012-03-11 23:47:41 +00:00
|
|
|
|
2011-11-16 19:31:42 +00:00
|
|
|
if (iter->curindex >= iter->pool->pchunk) {
|
|
|
|
|
iter->curchunk = iter->curchunk->next;
|
|
|
|
|
iter->curindex = 0;
|
|
|
|
|
}
|
2012-03-11 23:47:41 +00:00
|
|
|
|
2011-11-16 19:31:42 +00:00
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void *BLI_mempool_iterstep(BLI_mempool_iter *iter)
|
|
|
|
|
{
|
|
|
|
|
BLI_freenode *ret;
|
2012-03-11 23:47:41 +00:00
|
|
|
|
2011-11-16 19:31:42 +00:00
|
|
|
do {
|
|
|
|
|
ret = bli_mempool_iternext(iter);
|
2012-03-11 23:47:41 +00:00
|
|
|
}while (ret && ret->freeword == FREEWORD);
|
|
|
|
|
|
2011-11-16 19:31:42 +00:00
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-29 03:39:59 +00:00
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
/* optimized version of code above */
|
|
|
|
|
|
|
|
|
|
void *BLI_mempool_iterstep(BLI_mempool_iter *iter)
|
|
|
|
|
{
|
|
|
|
|
BLI_freenode *ret;
|
|
|
|
|
|
|
|
|
|
if (UNLIKELY(iter->pool->totused == 0)) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
if (LIKELY(iter->curchunk)) {
|
2012-03-01 23:14:51 +00:00
|
|
|
ret = (BLI_freenode *)(((char *)iter->curchunk->data) + iter->pool->esize * iter->curindex);
|
2011-12-29 03:39:59 +00:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (UNLIKELY(++iter->curindex >= iter->pool->pchunk)) {
|
|
|
|
|
iter->curindex = 0;
|
|
|
|
|
iter->curchunk = iter->curchunk->next;
|
|
|
|
|
}
|
|
|
|
|
} while (ret->freeword == FREEWORD);
|
2012-03-11 23:47:41 +00:00
|
|
|
|
2011-12-29 03:39:59 +00:00
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
2008-07-04 17:32:55 +00:00
|
|
|
void BLI_mempool_destroy(BLI_mempool *pool)
|
|
|
|
|
{
|
2012-03-01 23:14:51 +00:00
|
|
|
BLI_mempool_chunk *mpchunk = NULL;
|
2011-11-16 16:50:30 +00:00
|
|
|
|
2012-03-01 22:59:18 +00:00
|
|
|
if (pool->flag & BLI_MEMPOOL_SYSMALLOC) {
|
2011-11-16 16:50:30 +00:00
|
|
|
for (mpchunk = pool->chunks.first; mpchunk; mpchunk = mpchunk->next) {
|
2010-10-30 17:16:37 +00:00
|
|
|
free(mpchunk->data);
|
|
|
|
|
}
|
|
|
|
|
BLI_freelist(&(pool->chunks));
|
|
|
|
|
free(pool);
|
|
|
|
|
}
|
|
|
|
|
else {
|
2011-11-16 16:50:30 +00:00
|
|
|
for (mpchunk = pool->chunks.first; mpchunk; mpchunk = mpchunk->next) {
|
2010-10-30 17:16:37 +00:00
|
|
|
MEM_freeN(mpchunk->data);
|
|
|
|
|
}
|
|
|
|
|
BLI_freelistN(&(pool->chunks));
|
|
|
|
|
MEM_freeN(pool);
|
|
|
|
|
}
|
2008-07-08 02:22:37 +00:00
|
|
|
}
|