Хотя я не думаю, что это хорошая идея, одним из решений было бы иметь заранее выделенные сегменты разных размеров журнала 2 , глупый псевдокод:
class Allocator {
void* malloc(size_t size) {
int bucket = log2(size + sizeof(int));
int* pointer = reinterpret_cast<int*>(m_buckets[bucket].back());
m_buckets[bucket].pop_back();
*pointer = bucket; //Store which bucket this was allocated from
return pointer + 1; //Dont overwrite header
}
void free(void* pointer) {
int* temp = reinterpret_cast<int*>(pointer) - 1;
m_buckets[*temp].push_back(temp);
}
vector< vector<void*> > m_buckets;
};
(Вы, конечно, также замените std::vector
на простой массив + счетчик).
РЕДАКТИРОВАТЬ: Для того чтобы сделать это устойчивым (то есть справиться с ситуацией, когда корзина пуста), вам придется добавить некоторую форму ветвления.
РЕДАКТИРОВАТЬ 2: Вот небольшая безветвленная log2
функция:
//returns the smallest x such that value <= (1 << x)
int
log2(int value) {
union Foo {
int x;
float y;
} foo;
foo.y = value - 1;
return ((foo.x & (0xFF << 23)) >> 23) - 126; //Extract exponent (base 2) of floating point number
}
Это дает правильный результат для распределений <33554432 байта. Если вам нужны большие ассигнования, вам придется переключиться на удвоения. </p>
Вот ссылка на представление чисел с плавающей запятой в памяти.