]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Add pool_add_external_ref() to allow pools to reference other pools
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Fri, 5 May 2023 14:10:55 +0000 (17:10 +0300)
committerTimo Sirainen <timo.sirainen@open-xchange.com>
Mon, 20 Nov 2023 12:21:56 +0000 (14:21 +0200)
When the pool is destroyed, all its external references are unreferenced.

src/lib/lib.h
src/lib/mempool-alloconly.c
src/lib/mempool.c
src/lib/mempool.h

index 7d945780c775dacad79d639333cd365975e0db79..474fbf190b8cbd08e62808807221fd1053c728eb 100644 (file)
 #include "macros.h"
 #include "failures.h"
 
+typedef struct buffer buffer_t;
+typedef struct buffer string_t;
+
+#include "array-decl.h" /* ARRAY*()s may exist in any header */
 #include "malloc-overflow.h"
 #include "data-stack.h"
 #include "mempool.h"
@@ -57,7 +61,6 @@ struct ostream;
 
 typedef void lib_atexit_callback_t(void);
 
-#include "array-decl.h" /* ARRAY*()s may exist in any header */
 #include "bits.h"
 #include "hash-decl.h" /* HASH_TABLE*()s may exist in any header */
 #include "strfuncs.h"
index a9e8cd701a3593ae6ec07e6534e42e96a52c4df9..798ea84f903021ab36f6322a90e74716c3771a77 100644 (file)
@@ -348,6 +348,7 @@ static void pool_alloconly_unref(pool_t *pool)
        if (--apool->refcount > 0)
                return;
 
+       pool_external_refs_unref(&apool->pool);
        pool_alloconly_destroy(apool);
 }
 
index a657481f9342dc3bf7a02a291b9d23f2c6c5fef2..68ec8f668439989a8733b43045907a35e0641613 100644 (file)
@@ -1,6 +1,7 @@
 /* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */
 
 #include "lib.h"
+#include "array.h"
 
 /* The various implementations of pools API assume that they'll never be
    asked for more than SSIZE_T_MAX bytes.  This is a sanity check to make
@@ -23,3 +24,21 @@ size_t pool_get_exp_grown_size(pool_t pool, size_t old_size, size_t min_size)
        i_assert(exp_size >= min_size);
        return exp_size;
 }
+
+void pool_add_external_ref(pool_t pool, pool_t ref_pool)
+{
+       if (!array_is_created(&pool->external_refs))
+               i_array_init(&pool->external_refs, 1);
+       array_push_back(&pool->external_refs, &ref_pool);
+       pool_ref(ref_pool);
+}
+
+void pool_external_refs_unref(pool_t pool)
+{
+       if (array_is_created(&pool->external_refs)) {
+               pool_t external_pool;
+               array_foreach_elem(&pool->external_refs, external_pool)
+                       pool_unref(&external_pool);
+               array_free(&pool->external_refs);
+       }
+}
index 9c7aca058180878da7bfd0647fa80059257307d6..918a6d4e6e6f4e7646c986ac01ab3a2e9a8fbce6 100644 (file)
@@ -46,6 +46,7 @@ struct pool_vfuncs {
 
 struct pool {
        const struct pool_vfuncs *v;
+       ARRAY(pool_t) external_refs;
 
        bool alloconly_pool:1;
        bool datastack_pool:1;
@@ -86,6 +87,10 @@ pool_t pool_allocfree_create_clean(const char *name);
    old_size + 1. */
 size_t pool_get_exp_grown_size(pool_t pool, size_t old_size, size_t min_size);
 
+/* Reference another memory pool in the given pool. When the pool is freed,
+   the referenced memory pools are also unreferenced. */
+void pool_add_external_ref(pool_t pool, pool_t ref_pool);
+
 /* We require sizeof(type) to be <= UINT_MAX. This allows compiler to optimize
    away the entire MALLOC_MULTIPLY() call on 64bit systems. */
 #define p_new(pool, type, count) \
@@ -175,5 +180,6 @@ size_t pool_allocfree_get_total_alloc_size(pool_t pool);
 
 /* private: */
 void pool_system_free(pool_t pool, void *mem);
+void pool_external_refs_unref(pool_t pool);
 
 #endif