forked from enlightenment/efl
201 lines
4.3 KiB
C
201 lines
4.3 KiB
C
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "Evas_Data.h"
|
|
#include "evas_mempool.h"
|
|
|
|
//#define NOPOOL
|
|
|
|
typedef struct _Pool Pool;
|
|
|
|
struct _Pool
|
|
{
|
|
int usage;
|
|
void *base;
|
|
Pool *prev, *next;
|
|
};
|
|
|
|
|
|
Pool *
|
|
_evas_mp_pool_new(Evas_Mempool *pool)
|
|
{
|
|
#ifdef NOPOOL
|
|
static Pool thepool;
|
|
return &thepool;
|
|
#else
|
|
Pool *p;
|
|
void **ptr;
|
|
int item_alloc, i;
|
|
|
|
item_alloc =
|
|
((pool->item_size + sizeof(void *) - 1) / sizeof(void *)) * sizeof(void *);
|
|
p = malloc(sizeof(Pool) + (pool->pool_size * item_alloc));
|
|
ptr = (void **)(((unsigned char *)p) + sizeof(Pool));
|
|
p->usage = 0;
|
|
p->base = ptr;
|
|
for (i = 0; i < pool->pool_size - 1; i++)
|
|
{
|
|
*ptr = (void **)(((unsigned char *)ptr) + item_alloc);
|
|
ptr = *ptr;
|
|
}
|
|
*ptr = NULL;
|
|
return p;
|
|
#endif
|
|
}
|
|
|
|
void
|
|
_evas_mp_pool_free(Pool *p)
|
|
{
|
|
#if !defined(NOPOOL)
|
|
free(p);
|
|
#endif
|
|
}
|
|
|
|
void *
|
|
evas_mempool_malloc(Evas_Mempool *pool, int size)
|
|
{
|
|
#ifdef NOPOOL
|
|
return malloc(size);
|
|
#else
|
|
Pool *p;
|
|
void *mem;
|
|
|
|
for (p = pool->first; p; p = p->next) // look 4 pool from 2nd bucket on
|
|
{
|
|
if (p->base) // base is not NULL - has a free slot
|
|
{
|
|
if (p->prev)
|
|
{
|
|
if (pool->last == p)
|
|
pool->last = p->prev;
|
|
|
|
p->prev->next = p->next;
|
|
p->prev = NULL;
|
|
p->next = pool->first;
|
|
p->next->prev = p;
|
|
pool->first = p;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
if (!p) // we have reached the end of the list - no free pools
|
|
{
|
|
p = _evas_mp_pool_new(pool);
|
|
if (!p)
|
|
return NULL;
|
|
|
|
p->prev = NULL;
|
|
p->next = pool->first;
|
|
if (p->next)
|
|
p->next->prev = p;
|
|
|
|
if (!pool->last)
|
|
pool->last = p;
|
|
|
|
pool->first = p;
|
|
}
|
|
|
|
mem = p->base; // this points to the next free block - so take it
|
|
p->base = *((void **)mem); // base now points to the next free block
|
|
if (!p->base) // move to end - it just filled up
|
|
if (p->next)
|
|
{
|
|
if (p->prev)
|
|
p->prev->next = p->next;
|
|
else
|
|
pool->first = p->next;
|
|
|
|
p->next->prev = p->prev;
|
|
((Pool *)pool->last)->next = p;
|
|
p->prev = pool->last;
|
|
p->next = NULL;
|
|
pool->last = p;
|
|
}
|
|
|
|
p->usage++;
|
|
pool->usage++;
|
|
return mem;
|
|
#endif
|
|
}
|
|
|
|
void
|
|
evas_mempool_free(Evas_Mempool *pool, void *ptr)
|
|
{
|
|
#ifdef NOPOOL
|
|
free(ptr);
|
|
#else
|
|
Pool *p;
|
|
void *pmem;
|
|
int item_alloc, psize;
|
|
|
|
item_alloc =
|
|
((pool->item_size + sizeof(void *) - 1) / sizeof(void *)) * sizeof(void *);
|
|
psize = item_alloc * pool->pool_size;
|
|
for (p = (Pool *)(pool->first); p; p = p->next) // look 4 pool
|
|
{
|
|
pmem = (void *)(((unsigned char *)p) + sizeof(Pool)); // pool mem base
|
|
if ((ptr >= pmem) &&
|
|
((unsigned char *)ptr < (((unsigned char *)pmem) + psize))) // is it in pool mem?
|
|
{
|
|
*((void **)ptr) = p->base; // freed node points to prev free node
|
|
p->base = ptr; // next free node is now the one we freed
|
|
p->usage--;
|
|
pool->usage--;
|
|
if (p->usage == 0) // free bucket
|
|
{
|
|
if (p->prev)
|
|
p->prev->next = p->next;
|
|
|
|
if (p->next)
|
|
p->next->prev = p->prev;
|
|
|
|
if (pool->last == p)
|
|
pool->last = p->prev;
|
|
|
|
if (pool->first == p)
|
|
pool->first = p->next;
|
|
|
|
_evas_mp_pool_free(p);
|
|
}
|
|
else if (p->prev) // if not the first - move to front
|
|
{
|
|
p->prev->next = p->next;
|
|
if (p->next)
|
|
p->next->prev = p->prev;
|
|
|
|
if (pool->last == p)
|
|
pool->last = p->prev;
|
|
|
|
p->prev = NULL;
|
|
p->next = pool->first;
|
|
p->next->prev = p;
|
|
pool->first = p;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
void *
|
|
evas_mempool_calloc(Evas_Mempool *pool, int size)
|
|
{
|
|
#ifdef NOPOOL
|
|
return calloc(1, size);
|
|
#else
|
|
void *mem;
|
|
|
|
mem = evas_mempool_malloc(pool, size);
|
|
memset(mem, 0, size);
|
|
return mem;
|
|
#endif
|
|
}
|
|
|