MemoryContext
GenerationContextCreate(MemoryContext parent,constchar*name,Size blockSize){GenerationContext *set;...set =(GenerationContext *)malloc(MAXALIGN(sizeof(GenerationContext)));.../* Fill in GenerationContext-specific header fields */set->blockSize = blockSize;set->block =NULL;dlist_init(&set->blocks);/* Finally, do the type-independent part of context creation */MemoryContextCreate((MemoryContext) set,T_GenerationContext,&GenerationMethods,parent,name);return(MemoryContext) set;}
分配空间
分配空间大小大于block/8
计算需要分配空间
分配空间
初始化空间
将空间放入循环双向链表
if(chunk_size > set->blockSize /8){Size blksize = chunk_size + Generation_BLOCKHDRSZ + Generation_CHUNKHDRSZ;block =(GenerationBlock *)malloc(blksize);if(block ==NULL)returnNULL;context->mem_allocated += blksize;/* block with a single (used) chunk */block->blksize = blksize;block->nchunks =1;block->nfree =0;/* the block is completely full */block->freeptr = block->endptr =((char*) block)+ blksize;chunk =(GenerationChunk *)(((char*) block)+ Generation_BLOCKHDRSZ);chunk->block = block;chunk->context = set;chunk->size = chunk_size;.../* add the block to the list of allocated blocks */dlist_push_head(&set->blocks,&block->node);...returnGenerationChunkGetPointer(chunk);}
分配空间小于等于block/8
block为空或block剩余空间不足,则创建新的block
/** Not an over-sized chunk. Is there enough space in the current block? If* not, allocate a new "regular" block.*/block = set->block;if((block ==NULL)||(block->endptr - block->freeptr)< Generation_CHUNKHDRSZ + chunk_size){Size blksize = set->blockSize;block =(GenerationBlock *)malloc(blksize);if(block ==NULL)returnNULL;context->mem_allocated += blksize;block->blksize = blksize;block->nchunks =0;block->nfree =0;block->freeptr =((char*) block)+ Generation_BLOCKHDRSZ;block->endptr =((char*) block)+ blksize;.../* add it to the doubly-linked list of blocks */dlist_push_head(&set->blocks,&block->node);/* and also use it as the current allocation block */set->block = block;}
GenerationContext *set =(GenerationContext *) context;GenerationChunk *chunk =GenerationPointerGetChunk(pointer);GenerationBlock *block;...block = chunk->block;.../* Reset context to NULL in freed chunks */chunk->context =NULL;...block->nfree +=1;
如果nfree等于nchunks,删除节点,释放空间
/* If there are still allocated chunks in the block, we're done. */if(block->nfree < block->nchunks)return;/** The block is empty, so let's get rid of it. First remove it from the* list of blocks, then return it to malloc().*/dlist_delete(&block->node);/* Also make sure the block is not marked as the current block. */if(set->block == block)set->block =NULL;context->mem_allocated -= block->blksize;free(block);
销毁GenerationContext
遍历blocks,删除节点,释放节点空间
释放context
staticvoidGenerationReset(MemoryContext context){GenerationContext *set =(GenerationContext *) context;dlist_mutable_iter miter;...dlist_foreach_modify(miter,&set->blocks){GenerationBlock *block =dlist_container(GenerationBlock, node, miter.cur);dlist_delete(miter.cur);context->mem_allocated -= block->blksize;...free(block);}set->block =NULL;...}/** GenerationDelete* Free all memory which is allocated in the given context.*/staticvoidGenerationDelete(MemoryContext context){/* Reset to release all the GenerationBlocks */GenerationReset(context);/* And free the context header */free(context);}