Sample
Here is a bit of code manually converted to C3 from C.
struct Node
{
uint hole;
uint size;
Node* next;
Node* prev;
}
struct Footer
{
Node *header;
}
struct Bin
{
Node* head;
}
struct Heap
{
size start;
size end;
Bin* bins[BIN_COUNT];
}
const uint OFFSET = 8;
/**
* @require heap != nil, start > 0
*/
void Heap.init(Heap* heap, usz start)
{
Node* init_region = (Node*)start;
init_region.hole = 1;
init_region.size = HEAP_INIT_SIZE - Node.sizeof - Footer.sizeof;
init_region.createFoot();
heap.bins[get_bin_index(init_region.size)].add(init_region);
heap.start = (void*)start;
heap.end = (void*)(start + HEAP_INIT_SIZE);
}
void* Heap.alloc(Heap* heap, usz size)
{
uint index = get_bin_index(size);
Bin* temp = (Bin*)heap.bins[index];
Node* found = temp.getBestFit(size);
while (!found)
{
temp = heap.bins[++index];
found = temp.getBestFit(size);
}
if ((found.size - size) > (overhead + MIN_ALLOC_SZ))
{
Node* split = (Node*)((char*)found + Node.sizeof + Footer.sizeof) + size;
split.size = found.size - size - Node.sizeof - Footer.sizeof;
split.hole = 1;
split.createFoot();
uint new_idx = get_bin_index(split.size);
heap.bins[new_idx].addNode(split);
found.size = size;
found.createFoot(found);
}
found.hole = 0;
heap.bins[index].removeNode(found);
Node* wild = heap.getWilderness(heap);
if (wild.size < MIN_WILDERNESS)
{
uint success = heap.expand(0x1000);
if (success == 0)
{
return nil;
}
}
else if (wild.size > MAX_WILDERNESS)
{
heap.contract(0x1000);
}
found.prev = nil;
found.next = nil;
return &found.next;
}
/**
* @require p != nil
*/
fn void Heap.free(Heap* heap, void *p)
{
Bin* list;
Footer& new_foot, old_foot;
Node* head = (Node*)((char*)p - OFFSET);
if (head == (Node*)((uptr)heap.start))
{
head.hole = 1;
heap.bins[get_bin_index(head.size)].addNode(head);
return;
}
Node* next = (Node*)((char*)head.getFoot() + Footer.sizeof);
Footer* f = (Footer*)((char*)(head) - Footer.sizeof);
Node* prev = f.header;
if (prev.hole)
{
list = heap.bins[get_bin_index(prev.size)];
list.removeNode(prev);
prev.size += overhead + head.size;
new_foot = head.getFoot(head);
new_foot.header = prev;
head = prev;
}
if (next.hole) {
list = heap.bins[get_bin_index(next.size)];
list.removeNode(next);
head.size += overhead + next.size;
old_foot = next.getFoot();
old_foot.header = 0;
next.size = 0;
next.hole = 0;
new_foot = head.getFoot(head);
new_foot.header = head;
}
head.hole = 1;
heap.bins[get_bin_index(head.size)].addNode(head);
}
fn uint Heap.expand(Heap* heap, usz sz)
{
return 0;
}
fn void Heap.contract(Heap* heap, usz sz)
{
return;
}
fn uint get_bin_index(usz sz)
{
uint index = 0;
sz = sz < 4 ? 4 : sz;
while (sz >>= 1) index++;
index -= 2;
if (index > BIN_MAX_IDX) index = BIN_MAX_IDX;
return index;
}
fn void Node.createFoot(Node* head)
{
Footer* foot = head.getFoot();
foot.header = head;
}
fn Footer* Node.getFoot(Node* node)
{
return (Footer*)((char*)node + Node.sizeof + node.size);
}
fn Node* getWilderness(Heap* heap)
{
Footer* wild_foot = (Footer*)((char*)heap.end - Footer.sizeof);
return wild_foot.header;
}