Здравствуйте, Сергей Губанов, Вы писали:
СГ>Существует ли эффективное решение для этого частного случая?
1. Представить всю память, как последовательность 64-байтовых блоков
2. Завести битовый массив занятости, по биту на каждый 64-байтовый блок (можно по байту, для ускорения доступа)
3. Назовем "близнецами" два соседних 64-байтовых блока, если положение первого относительно начала памяти делится на 128. 128-байтные блоки выделять всегда, как пару 64-байтовых близнецов (удобнее начало памяти выровнять на 128, тогда можно работать с адресами блоков, а не со смещениями)
4. Завести 2 списка свободных блоков, один для 64-байтовых, другой — для 128-байтовых. Указатель на следующий хранить в самом свободном блоке
5. Изначально нарезать всю память на 128-байтовые блоки и поместить в соответствующий список
6. При аллокации 128-байтового блока смотрим на соответствующий список. Если там есть чего аллоцировать, аллоцируем
7. При аллокации 64-байтового блока смотрим сначала на соответствуюший список. Если там пусто, пытаемся зааллоцировать 128-байтовый блок, разрезаем его на две части, одну суем в список свободных 64-байтовых, вторую аллоцируем. В любом случае, если удалось зааллоцировать, помечаем блок, как занятый (в битовом массиве)
8. При освобождении 128-байтового блока просто суем его в соответствующий список
9. При освобождении 64-байтового блока смотрим в битовый массив, свободен ли его близнец. Если да, удаляем его из списка свободных 64-байтовых, и объединенный 128-байтовый засовываем в соответствующий список. Если нет, то просто засовываем освободившийся 64-байтовый блок в список свободный 64-байтовых, и помечаем, как свободный, в битовом массиве. Зная адрес 64-байтового блока, адрес близнеца вычислить несложно.
Списки понадобятся двунаправленные, чтобы можно было легко удалять элементы из середины.
Вроде все.
Более общая версия этого алгоритма известна, как
Buddy memory allocation