boost中的ordered_free为什么需要做排序
因为要用到boost中的pool,所以在网上查了下资料并整理如下:
Boost中的ordered_free则假设FreeNodeList是有序的,因此会遍历FreeNodeList把要释放的结点插入到合适的位置。
首先通过find_prev寻找 要加入的block在当前free list链中的位置,再将之加入free list,以使列表有序
代码如下:
find_prev(void * const ptr)
{
// Handle border case
if (first == 0 || std::greater<void *>()(first, ptr))
return 0;
void * iter = first;
while (true)
{
// if we're about to hit the end or
// if we've found where "ptr" goes
if (nextof(iter) == 0 || std::greater<void *>()(nextof(iter), ptr)) //指针地址升序排序
return iter;
iter = nextof(iter);
}
}
void ordered_free(void * const chunk)
{
// This (slower) implementation of 'free' places the memory
// back in the list in its proper order.
// Find where "chunk" goes in the free list
void * const loc = find_prev(chunk); //查找要加入链表的位置
// Place either at beginning or in middle/end
if (loc == 0)
free(chunk);
else
{
nextof(chunk) = nextof(loc);
nextof(loc) = chunk; //在loc结点后面加入chunk结点
}
}
为什么要在释放内存块时进行排序呢,原因是boost在这里支持了一个GC(自动回收内存(并自动执行析构函数))的功能。
看下object_pool::~object_pool函数的实现就一切真相大白了。
template <typename T, typename UserAllocator>
object_pool<T, UserAllocator>::~object_pool()
{
// Start ’freed_iter’ at beginning of free list
void * freed_iter = this->first;
const size_type partition_size = this->alloc_size();
do
{
// increment next
next = next.next();
// delete all contained objects that aren’t freed
// Iterate ’i' through all chunks in the memory block
for (char * i = iter.begin(); i != iter.end(); i += partition_size)
{
// If this chunk is free
if (i == freed_iter)
{
// Increment freed_iter to point to next in free list
freed_iter = nextof(freed_iter);
// Continue searching chunks in the memory block
continue;
}
// This chunk is not free (allocated), so call its destructor
static_cast<T *>(static_cast<void *>(i))->~T();
// and continue searching chunks in the memory block
}
// free storage
UserAllocator::free(iter.begin());
// increment iter
iter = next;
} while (iter.valid());
// Make the block list empty so that the inherited destructor doesn’t try to
// free it again.
this->list.invalidate();
}
object_pool遍历所有申请的内存块(MemBlock),并遍历其中所有结点(Node),如果该结点不出现在自由内存结点(FreeNode)的列表(FreeNodeList)中,
那么,它就是用户未主动释放的结点,需要进行相应的析构操作。