Se puede utilizar un cierre libre lista y un par de cubos de diferentes tamaños.
Así:
typedef struct
{
union{
SLIST_ENTRY entry;
void* list;
};
byte mem[];
} mem_block;
typedef struct
{
SLIST_HEADER root;
} mem_block_list;
#define BUCKET_COUNT 4
#define BLOCKS_TO_ALLOCATE 16
static mem_block_list Buckets[BUCKET_COUNT];
void init_buckets()
{
for(int i = 0; i < BUCKET_COUNT; ++i)
{
InitializeSListHead(&Buckets[i].root);
for(int j = 0; j < BLOCKS_TO_ALLOCATE; ++j)
{
mem_block* p = (mem_block*) malloc(sizeof(mem_block) + (0x1 << BUCKET_COUNT) * 0x8);
InterlockedPushEntrySList(&Buckets[i].root, &p->entry);
}
}
}
void* balloc(size_t size)
{
for(int i = 0; i < BUCKET_COUNT; ++i)
{
if(size <= (0x1 << i) * 0x8)
{
mem_block* p = (mem_block*) InterlockedPopEntrySList(&Buckets[i].root);
p->list = &Buckets[i];
}
}
return 0; // block to large
}
void bfree(void* p)
{
mem_block* block = (mem_block*) (((byte*)p) - sizeof(block->entry));
InterlockedPushEntrySList(((mem_block_list*)block)->root, &block->entry);
}
SLIST_ENTRY, InterlockedPushEntrySList, InterlockedPopEntrySList, InitializeSListHead
son funciones de las operaciones de lista única-ligado sin bloqueo bajo Win32. Use las operaciones correspondientes en otros sistemas operativos.
inconvenientes:
- sobrecarga de
sizeof(SLIST_ENTRY)
- Los cubos sólo pueden crecer de manera eficiente una vez al inicio, después de que se puede ejecutar sin memoria y tienen que pedir a los OS/otros cubos. (Otros cubos conduce a la fragmentación)
- Esta muestra es un poco demasiado fácil y debe ser extendido para manejar más casos
+1 gracias por el enlace – Viet
Este documento es lo primero que pensé cuando vi la pregunta. Usamos una variación de este asignador en uno de nuestros productos y fue realmente muy útil. –
Gracias Dan. ¡Esto suena genial! Así que obtuve confianza para mejorarlo. – Viet