[Bf-blender-cvs] [5cd1aaf0808] master: BLI_memarena: support merging memory arenas

Campbell Barton noreply at git.blender.org
Thu Jul 15 06:48:33 CEST 2021


Commit: 5cd1aaf0808f2bac11fadcf8c351429de54ac68a
Author: Campbell Barton
Date:   Thu Jul 15 14:37:26 2021 +1000
Branches: master
https://developer.blender.org/rB5cd1aaf0808f2bac11fadcf8c351429de54ac68a

BLI_memarena: support merging memory arenas

Useful when thread-local storage has it's own memory arena containing
data which is kept after the multi-threaded operation has finished.

===================================================================

M	source/blender/blenlib/BLI_memarena.h
M	source/blender/blenlib/intern/BLI_memarena.c

===================================================================

diff --git a/source/blender/blenlib/BLI_memarena.h b/source/blender/blenlib/BLI_memarena.h
index d7798f12fcc..b2e05b00735 100644
--- a/source/blender/blenlib/BLI_memarena.h
+++ b/source/blender/blenlib/BLI_memarena.h
@@ -50,6 +50,8 @@ void *BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESU
 void *BLI_memarena_calloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT
     ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2);
 
+void BLI_memarena_merge(MemArena *ma_dst, MemArena *ma_src) ATTR_NONNULL(1, 2);
+
 void BLI_memarena_clear(MemArena *ma) ATTR_NONNULL(1);
 
 #ifdef __cplusplus
diff --git a/source/blender/blenlib/intern/BLI_memarena.c b/source/blender/blenlib/intern/BLI_memarena.c
index fc381c22315..de2ce44be44 100644
--- a/source/blender/blenlib/intern/BLI_memarena.c
+++ b/source/blender/blenlib/intern/BLI_memarena.c
@@ -45,6 +45,7 @@
 #  define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) UNUSED_VARS(pool, rzB, is_zeroed)
 #  define VALGRIND_DESTROY_MEMPOOL(pool) UNUSED_VARS(pool)
 #  define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) UNUSED_VARS(pool, addr, size)
+#  define VALGRIND_MOVE_MEMPOOL(pool_a, pool_b) UNUSED_VARS(pool_a, pool_b)
 #endif
 
 struct MemBuf {
@@ -178,6 +179,55 @@ void *BLI_memarena_calloc(MemArena *ma, size_t size)
   return ptr;
 }
 
+/**
+ * Transfer ownership of allocated blocks from `ma_src` into `ma_dst`,
+ * cleaning the contents of `ma_src`.
+ *
+ * \note Useful for multi-threaded tasks that need a thread-local #MemArena
+ * that is kept after the multi-threaded operation is completed.
+ */
+void BLI_memarena_merge(MemArena *ma_dst, MemArena *ma_src)
+{
+  /* Memory arenas must be compatible. */
+  BLI_assert(ma_dst != ma_src);
+  BLI_assert(ma_dst->align == ma_src->align);
+  BLI_assert(ma_dst->use_calloc == ma_src->use_calloc);
+  BLI_assert(ma_dst->bufsize == ma_src->bufsize);
+
+  if (ma_src->bufs == NULL) {
+    return;
+  }
+
+  if (UNLIKELY(ma_dst->bufs == NULL)) {
+    BLI_assert(ma_dst->curbuf == NULL);
+    ma_dst->bufs = ma_src->bufs;
+    ma_dst->curbuf = ma_src->curbuf;
+    ma_dst->cursize = ma_src->cursize;
+  }
+  else {
+    /* Keep the 'ma_dst->curbuf' for simplicity.
+     * Insert buffers after the first. */
+    if (ma_dst->bufs->next != NULL) {
+      /* Loop over `ma_src` instead of `ma_dst` since it's likely the destination is larger
+       * when used for accumulating from multiple sources. */
+      struct MemBuf *mb_src = ma_src->bufs;
+      mb_src = ma_src->bufs;
+      while (mb_src && mb_src->next) {
+        mb_src = mb_src->next;
+      }
+      mb_src->next = ma_dst->bufs->next;
+    }
+    ma_dst->bufs->next = ma_src->bufs;
+  }
+
+  ma_src->bufs = NULL;
+  ma_src->curbuf = NULL;
+  ma_src->cursize = 0;
+
+  VALGRIND_MOVE_MEMPOOL(ma_src, ma_dst);
+  VALGRIND_CREATE_MEMPOOL(ma_src, 0, false);
+}
+
 /**
  * Clear for reuse, avoids re-allocation when an arena may
  * otherwise be free'd and recreated.



More information about the Bf-blender-cvs mailing list