diff --git a/src/backend/utils/mmgr/README b/src/backend/utils/mmgr/README index 45e610dd061f01fbc9f94222c0857da23da0076f..4ebb78e4eb046a611f3eb74de5b7e76a86058d90 100644 --- a/src/backend/utils/mmgr/README +++ b/src/backend/utils/mmgr/README @@ -125,9 +125,14 @@ lifetimes that only partially overlap can be handled by allocating from different trees of the context forest (there are some examples in the next section). -For convenience we will also want operations like "reset/delete all -children of a given context, but don't reset or delete that context -itself". +Actually, it turns out that resetting a given context should almost +always imply deleting (not just resetting) any child contexts it has. +So MemoryContextReset() means that, and if you really do want a tree of +empty contexts you need to call MemoryContextResetOnly() plus +MemoryContextResetChildren(). + +For convenience we also provide operations like "reset/delete all children +of a given context, but don't reset or delete that context itself". Globally Known Contexts diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c index 72a32abdddb671769d8999a3f30b009ea603b900..e2fbfd420b661bdcc88b9bcb023414425fb46b8c 100644 --- a/src/backend/utils/mmgr/mcxt.c +++ b/src/backend/utils/mmgr/mcxt.c @@ -132,11 +132,8 @@ MemoryContextInit(void) /* * MemoryContextReset - * Release all space allocated within a context and its descendants, - * but don't delete the contexts themselves. - * - * The type-specific reset routine handles the context itself, but we - * have to do the recursion for the children. + * Release all space allocated within a context and delete all its + * descendant contexts (but not the named context itself). */ void MemoryContextReset(MemoryContext context) @@ -145,7 +142,22 @@ MemoryContextReset(MemoryContext context) /* save a function call in common case where there are no children */ if (context->firstchild != NULL) - MemoryContextResetChildren(context); + MemoryContextDeleteChildren(context); + + /* save a function call if no pallocs since startup or last reset */ + if (!context->isReset) + MemoryContextResetOnly(context); +} + +/* + * MemoryContextResetOnly + * Release all space allocated within a context. + * Nothing is done to the context's descendant contexts. + */ +void +MemoryContextResetOnly(MemoryContext context) +{ + AssertArg(MemoryContextIsValid(context)); /* Nothing to do if no pallocs since startup or last reset */ if (!context->isReset) @@ -172,7 +184,10 @@ MemoryContextResetChildren(MemoryContext context) AssertArg(MemoryContextIsValid(context)); for (child = context->firstchild; child != NULL; child = child->nextchild) - MemoryContextReset(child); + { + MemoryContextResetChildren(child); + MemoryContextResetOnly(child); + } } /* @@ -234,23 +249,6 @@ MemoryContextDeleteChildren(MemoryContext context) MemoryContextDelete(context->firstchild); } -/* - * MemoryContextResetAndDeleteChildren - * Release all space allocated within a context and delete all - * its descendants. - * - * This is a common combination case where we want to preserve the - * specific context but get rid of absolutely everything under it. - */ -void -MemoryContextResetAndDeleteChildren(MemoryContext context) -{ - AssertArg(MemoryContextIsValid(context)); - - MemoryContextDeleteChildren(context); - MemoryContextReset(context); -} - /* * MemoryContextRegisterResetCallback * Register a function to be called before next context reset/delete. diff --git a/src/include/utils/memutils.h b/src/include/utils/memutils.h index 76ad7d443b03053f4637467e72d2f1bb1fc4f26a..dbb163a15364cb79254d9f43d68531b17edabf36 100644 --- a/src/include/utils/memutils.h +++ b/src/include/utils/memutils.h @@ -84,6 +84,9 @@ extern PGDLLIMPORT MemoryContext CurTransactionContext; /* This is a transient link to the active portal's memory context: */ extern PGDLLIMPORT MemoryContext PortalContext; +/* Backwards compatibility macro */ +#define MemoryContextResetAndDeleteChildren(ctx) MemoryContextReset(ctx) + /* * Memory-context-type-independent functions in mcxt.c @@ -91,9 +94,9 @@ extern PGDLLIMPORT MemoryContext PortalContext; extern void MemoryContextInit(void); extern void MemoryContextReset(MemoryContext context); extern void MemoryContextDelete(MemoryContext context); +extern void MemoryContextResetOnly(MemoryContext context); extern void MemoryContextResetChildren(MemoryContext context); extern void MemoryContextDeleteChildren(MemoryContext context); -extern void MemoryContextResetAndDeleteChildren(MemoryContext context); extern void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb); extern void MemoryContextSetParent(MemoryContext context,