#include <stdio.h>
#include <stdlib.h>
#include "../Include/tesselator.h"
typedef struct BucketAlloc BucketAlloc;
typedef struct Bucket Bucket;
struct Bucket
{
Bucket *next;
};
struct BucketAlloc
{
void *freelist;
Bucket *buckets;
unsigned int itemSize;
unsigned int bucketSize;
const char *name;
TESSalloc* alloc;
};
static int CreateBucket( struct BucketAlloc* ba )
{
size_t size;
Bucket* bucket;
void* freelist;
unsigned char* head;
unsigned char* it;
size = sizeof(Bucket) + ba->itemSize * ba->bucketSize;
bucket = (Bucket*)ba->alloc->memalloc( ba->alloc->userData, size );
if ( !bucket )
return 0;
bucket->next = 0;
bucket->next = ba->buckets;
ba->buckets = bucket;
freelist = ba->freelist;
head = (unsigned char*)bucket + sizeof(Bucket);
it = head + ba->itemSize * ba->bucketSize;
do
{
it -= ba->itemSize;
*((void**)it) = freelist;
freelist = (void*)it;
}
while ( it != head );
ba->freelist = (void*)it;
return 1;
}
static void *NextFreeItem( struct BucketAlloc *ba )
{
return *(void**)ba->freelist;
}
struct BucketAlloc* createBucketAlloc( TESSalloc* alloc, const char* name,
unsigned int itemSize, unsigned int bucketSize )
{
BucketAlloc* ba = (BucketAlloc*)alloc->memalloc( alloc->userData, sizeof(BucketAlloc) );
ba->alloc = alloc;
ba->name = name;
ba->itemSize = itemSize;
if ( ba->itemSize < sizeof(void*) )
ba->itemSize = sizeof(void*);
ba->bucketSize = bucketSize;
ba->freelist = 0;
ba->buckets = 0;
if ( !CreateBucket( ba ) )
{
alloc->memfree( alloc->userData, ba );
return 0;
}
return ba;
}
void* bucketAlloc( struct BucketAlloc *ba )
{
void *it;
if ( !ba->freelist || !NextFreeItem( ba ) )
{
if ( !CreateBucket( ba ) )
return 0;
}
it = ba->freelist;
ba->freelist = NextFreeItem( ba );
return it;
}
void bucketFree( struct BucketAlloc *ba, void *ptr )
{
#ifdef CHECK_BOUNDS
int inBounds = 0;
Bucket *bucket;
bucket = ba->buckets;
while ( bucket )
{
void *bucketMin = (void*)((unsigned char*)bucket + sizeof(Bucket));
void *bucketMax = (void*)((unsigned char*)bucket + sizeof(Bucket) + ba->itemSize * ba->bucketSize);
if ( ptr >= bucketMin && ptr < bucketMax )
{
inBounds = 1;
break;
}
bucket = bucket->next;
}
if ( inBounds )
{
*(void**)ptr = ba->freelist;
ba->freelist = ptr;
}
else
{
printf("ERROR! pointer 0x%p does not belong to allocator '%s'\n", ba->name);
}
#else
*(void**)ptr = ba->freelist;
ba->freelist = ptr;
#endif
}
void deleteBucketAlloc( struct BucketAlloc *ba )
{
TESSalloc* alloc = ba->alloc;
Bucket *bucket = ba->buckets;
Bucket *next;
while ( bucket )
{
next = bucket->next;
alloc->memfree( alloc->userData, bucket );
bucket = next;
}
ba->freelist = 0;
ba->buckets = 0;
alloc->memfree( alloc->userData, ba );
}