// Copyright (c) Vitaliy Filippov, 2023+ // License: VNPL-1.1 or GNU GPL-2.0+ (see README.md for details) #include #include "freelist.h" uint64_t freelist_allocator_t::alloc(uint64_t data_size) { for (int i = 0; i < freelist.size(); i++) { if (freelist[i].size >= data_size) { uint64_t r = freelist[i].start; freelist[i].start += data_size; freelist[i].size -= data_size; return r; } } return UINT64_MAX; } void freelist_allocator_t::free(uint64_t start, uint64_t size) { int min = 0, max = freelist.size(); if (max && freelist[freelist.size()-1].start < start) { min = max; } if (max && freelist[0].start >= start) { max = 0; } while (max-min > 1) { int mid = (min+max)/2; if (freelist[mid].start >= start) max = mid; else min = mid; } // max = the first item where freelist[max].start >= start if (max > 0 && freelist[max-1].start+freelist[max-1].size >= start) { assert(freelist[max-1].start+freelist[max-1].size == start); freelist[max-1].size += size; } else if (max < freelist.size() && freelist[max].start <= size+start) { assert(freelist[max].start == size+start); freelist[max].start -= size; freelist[max].size += size; } else { freelist.insert(freelist.begin()+min, (freelist_item_t){ .start = start, .size = size }); max = min; // to skip the if below } if (min != max && max < freelist.size() && freelist[max].start == freelist[min].start+freelist[min].size) { freelist[min].size += freelist[max].size; freelist.erase(freelist.begin()+max, freelist.begin()+max+1); } }