分类: LINUX
2011-10-08 15:47:12
SizeMap初始化完成后,initStaticVars()开始初始化span_allocator_.Init(),并调用两次,主要目的应该是为了能够成功初始化,并保证cache不会存在冲突。;span_allocator_是一个PageHeapAllocator(page_heap_allocator.h)模板的span实例。span_allocator_.Init()函数比较诡异,开始先将几个数据结构初始化,在最后一行调用了New后立即Delete这部分内容非常有意思。
void Init() {
ASSERT(sizeof(T) <= kAllocIncrement);
inuse_ = 0;
free_area_ = NULL;
free_avail_ = 0;
free_list_ = NULL;
// Reserve some space at the beginning to avoid fragmentation.
Delete(New());
}
我们可以看看New和Delete函数,New函数首先判断free_list是否为NULL,如果非NULL,代表着已经有切出来的object可以用,然后直接从此list里面进行分配(这里面还有个小的技巧,留着后面理解)。如果free_list_为NULL,首先判断,是否有足够的已经分配的空间可用,如果有直接从free_area位置切出一块需要的空间,否则得从系统主动malloc出128k的空间然后开始分配,并调整free_area_,free_avail_和inuse_参数,并返回相应的地址。
T* New() {
// Consult free list
void* result;
if (free_list_ != NULL) {
result = free_list_;
free_list_ = *(reinterpret_cast
} else {
if (free_avail_ < sizeof(T)) {
// Need more room. We assume that MetaDataAlloc returns
// suitably aligned memory.
free_area_ = reinterpret_cast
// kAllocIncrement = 128 << 10
if (free_area_ == NULL) {
CRASH("FATAL ERROR: Out of memory trying to allocate internal "
"tcmalloc data (%d bytes, object-size %d)\n",
kAllocIncrement, static_cast
}
free_avail_ = kAllocIncrement;
}
result = free_area_;
free_area_ += sizeof(T);
free_avail_ -= sizeof(T);
}
inuse_++;
return reinterpret_cast
}
Delete函数并不真正的free空间,只是将此obj加入已经被切割obj并且空闲的列表,这里面有个非常有意思的东西,就是通过将下一个obj的地址存在当前obj里面,来进行管理,这样可以和上面New函数中红色部分相对应,通过当前位置free_list_中所存放的地址就可以找到下一个空闲地址。。
void Delete(T* p) {
*(reinterpret_cast
free_list_ = p;
inuse_--;
}