@ -178,26 +178,8 @@ MemoryContextDelete(MemoryContext context)
* there ' s an error we won ' t have deleted / busted contexts still attached
* there ' s an error we won ' t have deleted / busted contexts still attached
* to the context tree . Better a leak than a crash .
* to the context tree . Better a leak than a crash .
*/
*/
if ( context - > parent )
MemoryContextSetParent ( context , NULL ) ;
{
MemoryContext parent = context - > parent ;
if ( context = = parent - > firstchild )
parent - > firstchild = context - > nextchild ;
else
{
MemoryContext child ;
for ( child = parent - > firstchild ; child ; child = child - > nextchild )
{
if ( context = = child - > nextchild )
{
child - > nextchild = context - > nextchild ;
break ;
}
}
}
}
( * context - > methods - > delete_context ) ( context ) ;
( * context - > methods - > delete_context ) ( context ) ;
pfree ( context ) ;
pfree ( context ) ;
}
}
@ -237,6 +219,67 @@ MemoryContextResetAndDeleteChildren(MemoryContext context)
MemoryContextReset ( context ) ;
MemoryContextReset ( context ) ;
}
}
/*
* MemoryContextSetParent
* Change a context to belong to a new parent ( or no parent ) .
*
* We provide this as an API function because it is sometimes useful to
* change a context ' s lifespan after creation . For example , a context
* might be created underneath a transient context , filled with data ,
* and then reparented underneath CacheMemoryContext to make it long - lived .
* In this way no special effort is needed to get rid of the context in case
* a failure occurs before its contents are completely set up .
*
* Callers often assume that this function cannot fail , so don ' t put any
* elog ( ERROR ) calls in it .
*
* A possible caller error is to reparent a context under itself , creating
* a loop in the context graph . We assert here that context ! = new_parent ,
* but checking for multi - level loops seems more trouble than it ' s worth .
*/
void
MemoryContextSetParent ( MemoryContext context , MemoryContext new_parent )
{
AssertArg ( MemoryContextIsValid ( context ) ) ;
AssertArg ( context ! = new_parent ) ;
/* Delink from existing parent, if any */
if ( context - > parent )
{
MemoryContext parent = context - > parent ;
if ( context = = parent - > firstchild )
parent - > firstchild = context - > nextchild ;
else
{
MemoryContext child ;
for ( child = parent - > firstchild ; child ; child = child - > nextchild )
{
if ( context = = child - > nextchild )
{
child - > nextchild = context - > nextchild ;
break ;
}
}
}
}
/* And relink */
if ( new_parent )
{
AssertArg ( MemoryContextIsValid ( new_parent ) ) ;
context - > parent = new_parent ;
context - > nextchild = new_parent - > firstchild ;
new_parent - > firstchild = context ;
}
else
{
context - > parent = NULL ;
context - > nextchild = NULL ;
}
}
/*
/*
* GetMemoryChunkSpace
* GetMemoryChunkSpace
* Given a currently - allocated chunk , determine the total space
* Given a currently - allocated chunk , determine the total space
@ -489,6 +532,7 @@ MemoryContextCreate(NodeTag tag, Size size,
( * node - > methods - > init ) ( node ) ;
( * node - > methods - > init ) ( node ) ;
/* OK to link node to parent (if any) */
/* OK to link node to parent (if any) */
/* Could use MemoryContextSetParent here, but doesn't seem worthwhile */
if ( parent )
if ( parent )
{
{
node - > parent = parent ;
node - > parent = parent ;