È possibile utilizzare un blocco gratuito elenco e un paio di secchi di diverse dimensioni.
Quindi:
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
sono funzioni per le operazioni-linked-lista unica senza blocchi sotto Win32. Utilizzare le operazioni corrispondenti su altri sistemi operativi.
Svantaggi:
- Overhead di
sizeof(SLIST_ENTRY)
- I secchi possono crescere in modo efficiente solo una volta alla partenza, dopo che si può esaurire la memoria e devono chiedere agli OS/altri secchi. (Altri secchi porta ad frammentazione)
- questo esempio è un po 'troppo facile e deve essere esteso per gestire più casi
+1 grazie per il collegamento – Viet
Questo documento è la prima cosa a cui ho pensato quando ho visto la domanda. Abbiamo utilizzato una variazione di questo allocatore in uno dei nostri prodotti ed è stato davvero molto utile. –
Grazie Dan. Questo suona alla grande! Così ho preso confidenza per migliorarlo. – Viet