话说MemoryContextMethods结构里的函数实现了pg里AllocSet/MemoryContext的内存管理机制,定义见下面。
typedef structMemoryContextMethods
{
void *(*alloc) (MemoryContext context, Sizesize);
/* call this free_p in case someone #define's free() */
void (*free_p)(MemoryContext context, void *pointer);
void *(*realloc) (MemoryContext context, void *pointer, Size size);
void (*init)(MemoryContext context);
void (*reset)(MemoryContext context);
void (*delete) (MemoryContext context);
Size (*get_chunk_space) (MemoryContext context, void *pointer);
bool (*is_empty)(MemoryContext context);
void (*stats)(MemoryContext context);
#ifdef MEMORY_CONTEXT_CHECKING
void (*check)(MemoryContext context);
#endif
} MemoryContextMethods;
其中delete由AllocSet的静态函数AllocSetDelete()实现,具体签名在下面。它实现了AllocSet相关的内存删除机制。而MemoryContext即父类的内存删除由MemoryContextDelete()实现,签名在下面。这两个方法各自负责本类型中成员的内存删除工作,好像协作,完成了AllocSet/MemoryContext类型对象的删除和内存回收工作。
static void AllocSetDelete(MemoryContextcontext)
void MemoryContextDelete(MemoryContext context)
下面就写MemoryContextMethods.delete的实现者负责AllocSet实例删除的AllocSetDelete()这个函数以及相关的负责MemoryContext实例删除的MemoryContextDelete()方法。先上图,然后分块解读处理流程。
AllocSet/MemoryContext实例内存删除流程图
先说红色框吧,在红色框部分,MemoryContextDelete方法检查要删除的context是否有效,然后调用MemoryContextDeleteChildren方法,检查context的firstchild是否不为空,若不空就以firstchild指向的子context为参数调用MemoryContextDelete方法。这样就以MemoryContextDelete方法和MemoryContextDeleteChildren方法形成了递归调用,以删除当前的context及它的子context。
接着看黄色框,在前面形成递归调用的基础上,黄色框中主要是删除context及其子context的nextchild指向的子context。
再接着看蓝色框,主要是在前面形成递归调用的基础上,针对要删除的context及其子context调用AllocSetDelelte方法,处理context的aset和blocks成员,把aset置空,把AllocBlock列表blocks中的block使用过的内存空间逐个置0X7F,然后调free释放。这个blocks链表处理完后就到了绿色框中。
现在看绿色框和紫色框,在绿色框中,还是在前面形成递归调用的基础上,在绿色框中检查要删除的context的有效性,然后找到该context所在的AllockChunk类型实例chunk,根据该chunk找到其所属的context,把要删除的context和其所在的chunk所属的context一起作为参数调用AllocSetFree方法去释放要删除的context所占内存。AllocSetFree释放内存在《pg的内存管理机制二》中已经讨论过了,感兴趣可以去看一下。
这样就在以MemoryContextDelete方法和MemoryContextDeleteChildren方法形成的递归调用里逐个删除要删除的context及其firstchild和nextchild成员“链”上的context。具体看流程图吧。
结合图形看一个递归删除MemoryContext类型实例时的顺序的例子,图中一个圆圈代表一个MemoryContext类型实例,在左下方的是MemoryContext的firstshild成员,在右下方的是nextchild成员。图一是初始时的样子,现在要删除节点4,先顺着4的firstchild递归到其最终叶子节点6,将其按上面说的过程删除并释放空间,如图二。然后将节点4的nextchild节点7放到4的父节点3的nextchild子节点上,把节点3原来的nextchild子节点5放到节点7的nenxtchild子节点上,如图三。这时已经处理完了节点4的两个子节点,将节点4删除。
就到这儿吧。