ryContext类型的局部变量node,分配内存并初始化。注意,这时还没有初始化TopMemoryContext,所以node的内存空间是malloc出来的。MemoryContext类型的局部变量node初始化完后返回。
MemoryContext
MemoryContextCreate(NodeTag tag, Size size,
MemoryContextMethods*methods,
MemoryContextparent,
const char *name)
{
MemoryContext node;
Size needed = size + strlen(name) + 1;
if(TopMemoryContext == NULL)
{
/*Special case for startup: use good ol' malloc */
node = (MemoryContext)malloc(needed);
Assert(node != NULL);
}
/*Initialize the node as best we can */
MemSet(node, 0, size);
node->type = tag;
node->methods = methods;
node->parent = NULL; /* for themoment */
node->firstchild = NULL;
node->nextchild = NULL;
node->name = ((char *) node) + size;
strcpy(node->name, name);
/*Return to type-specific creation routine to finish up */
return node;
}
AllocSetContextCreate()函数得到从MemoryContextCreate()函数返回的MemoryContextCreate类型的值后转换为AllocSet类型,赋给context,把context其他属性初始化。最后又把context的类型由AllocSet转换为MemoryContext后返回给调用方法,赋值给TopMemoryContext。至此TopMemoryContext初始化完成。
代码见下面。
MemoryContext
AllocSetContextCreate(MemoryContext parent,
constchar *name,
Size minContextSize,
Size initBlockSize,
Size maxBlockSize)
{
AllocSet context;
/* Dothe type-independent part of context creation */
context = (AllocSet) MemoryContextCreate(T_AllocSetContext,
sizeof(AllocSetContext),
&AllocSetMethods,
parent,
name);
context->initBlockSize =initBlockSize;
context->maxBlockSize =maxBlockSize;
context->nextBlockSize =initBlockSize;
context->isReset = true;
return(MemoryContext) context;
}
在初始化TomMemoryContext的过程中,先按AllocSet的类型初始化一个MemoryContext类型的变量,然后把这个变量转成AllocSet类型,初始化AllocSet类型的其它成员,再将其转成MemoryContext类型的变量后赋值给TopMemoryContext。为什么能做这两次类型转换呢?见下面分解。
下面上个图看看初始化出来的TopMemoryContext的结构图(以后所有内存结构图都是低地址在下面,高地址在上面,再后面有内存结构图时就不标低地址位了):
TopMemoryContext的内存结构图
TopMemoryContext转成AllocSet类型后的内存结构图
上图中分两块说,先看左边的大方块。其中下面深蓝色部分是MemoryContextData的内存结构,深蓝色和上面的浅颜色部分合起来是AllocSetContext的内存结构。
初始化TopMemoryContext的时候,分配的内存大小不是按MemoryContextData结构的大小分的,是按AllocSetContext的大小分的内存,又在紧挨着上面分配了17个字节记录这个MemoryContextData /AllocSetContext 的名字“TopMemoryContext”。
能在初始化TopMemoryContext的过程中能在类型MemoryContextData 、AllocSetContext之间相互转化,是利用了AllocSetContext结构布局上的特点,刚一开始就是个MemoryContextData,接着是其它成员,这样要是把TopMemoryContext当MemoryContextData类型处理,就是上面那个图,图中黑色部分相当于未知,不用管它,剩下的就是MemoryContextData类型,当TopMemoryContext是AllocSetContext类型时,就面的图,它就是个AllocSetContext类型的变量了。这样做的好处是在一个结构里既能管理内存空间,又能管理内存空间里的内容,而且逻辑功能划分很清晰。
哦,有人说从中看出了面向对象编程中继承的影子,嗯、啊,是有点,如果MemoryContextData是父类,AllocSetContext是MemoryContextData的子类,看起来是挺像的,从内存布局上看子类里也少了指向vitualtable 的member function /viturl member function pointer(vptr)。看来从面向对象编程到面向过程编程是技术的渐进,就像设备的升级改造。扯的有点远了,打住。