aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2011-09-11 16:29:42 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2011-09-11 16:29:42 -0400
commitb0025bd95703aaedc4ff23ddcfbde9597fa0919d (patch)
tree23e4a900474f51b2c7932fffcf276e8141e0c389 /src
parent5f42e5945b3dd96c228531c0730f418846ced04e (diff)
downloadpostgresql-b0025bd95703aaedc4ff23ddcfbde9597fa0919d.tar.gz
postgresql-b0025bd95703aaedc4ff23ddcfbde9597fa0919d.zip
Invent a new memory context primitive, MemoryContextSetParent.
This function will be useful for altering the lifespan of a context after creation (for example, by creating it under a transient context and later reparenting it to belong to a long-lived context). It costs almost no new code, since we can refactor what was there. Per my proposal of yesterday.
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/mmgr/mcxt.c82
-rw-r--r--src/include/utils/memutils.h2
2 files changed, 65 insertions, 19 deletions
diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c
index 7ed35d5bdf1..4eab24c46c7 100644
--- a/src/backend/utils/mmgr/mcxt.c
+++ b/src/backend/utils/mmgr/mcxt.c
@@ -178,26 +178,8 @@ MemoryContextDelete(MemoryContext context)
* there's an error we won't have deleted/busted contexts still attached
* to the context tree. Better a leak than a crash.
*/
- if (context->parent)
- {
- MemoryContext parent = context->parent;
-
- if (context == parent->firstchild)
- parent->firstchild = context->nextchild;
- else
- {
- MemoryContext child;
+ MemoryContextSetParent(context, NULL);
- for (child = parent->firstchild; child; child = child->nextchild)
- {
- if (context == child->nextchild)
- {
- child->nextchild = context->nextchild;
- break;
- }
- }
- }
- }
(*context->methods->delete_context) (context);
pfree(context);
}
@@ -238,6 +220,67 @@ MemoryContextResetAndDeleteChildren(MemoryContext 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
* Given a currently-allocated chunk, determine the total space
* it occupies (including all memory-allocation overhead).
@@ -489,6 +532,7 @@ MemoryContextCreate(NodeTag tag, Size size,
(*node->methods->init) (node);
/* OK to link node to parent (if any) */
+ /* Could use MemoryContextSetParent here, but doesn't seem worthwhile */
if (parent)
{
node->parent = parent;
diff --git a/src/include/utils/memutils.h b/src/include/utils/memutils.h
index 7c1202478e5..94c78289b6e 100644
--- a/src/include/utils/memutils.h
+++ b/src/include/utils/memutils.h
@@ -90,6 +90,8 @@ extern void MemoryContextDelete(MemoryContext context);
extern void MemoryContextResetChildren(MemoryContext context);
extern void MemoryContextDeleteChildren(MemoryContext context);
extern void MemoryContextResetAndDeleteChildren(MemoryContext context);
+extern void MemoryContextSetParent(MemoryContext context,
+ MemoryContext new_parent);
extern Size GetMemoryChunkSpace(void *pointer);
extern MemoryContext GetMemoryChunkContext(void *pointer);
extern bool MemoryContextIsEmpty(MemoryContext context);