[Bf-blender-cvs] [476610dfae1] soc-2021-adaptive-cloth: bli: generational_arena: insert_with() and try_insert_with()

ishbosamiya noreply at git.blender.org
Sat Jun 19 20:24:17 CEST 2021


Commit: 476610dfae14b012fe90795e3ec5b90585a3c5c1
Author: ishbosamiya
Date:   Sat Jun 19 23:54:06 2021 +0530
Branches: soc-2021-adaptive-cloth
https://developer.blender.org/rB476610dfae14b012fe90795e3ec5b90585a3c5c1

bli: generational_arena: insert_with() and try_insert_with()

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

M	source/blender/blenlib/BLI_generational_arena.hh
M	source/blender/blenlib/tests/BLI_generational_arena_test.cc

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

diff --git a/source/blender/blenlib/BLI_generational_arena.hh b/source/blender/blenlib/BLI_generational_arena.hh
index 3e9a12450a2..2d588907a06 100644
--- a/source/blender/blenlib/BLI_generational_arena.hh
+++ b/source/blender/blenlib/BLI_generational_arena.hh
@@ -252,6 +252,50 @@ class Arena {
     return Index::invalid();
   }
 
+  /* TODO(ish): add optimization by moving `f`, can be done by
+   * returning value if `try_insert()` fails */
+  std::optional<Index> try_insert_with(std::function<T(Index)> f)
+  {
+    if (this->next_free_head) {
+      auto loc = *this->next_free_head;
+
+      if (auto entry = std::get_if<EntryNoExist>(&this->data[loc])) {
+        this->next_free_head = entry->next_free;
+        Index index(loc, this->generation);
+        T value = f(index);
+        this->data[loc] = EntryExist(value, this->generation);
+        this->length += 1;
+
+        return index;
+      }
+
+      /* The linked list created to
+       * know where to insert next is
+       * corrupted.
+       * `this->next_free_head` is corrupted */
+      BLI_assert_unreachable();
+    }
+    return std::nullopt;
+  }
+
+  Index insert_with(std::function<T(Index)> f)
+  {
+    if (auto index = this->try_insert_with(f)) {
+      return *index;
+    }
+
+    /* couldn't insert the value within reserved memory space */
+    const auto reserve_cap = this->data.size() == 0 ? 1 : this->data.size();
+    this->reserve(reserve_cap * 2);
+    if (auto index = this->try_insert_with(f)) {
+      return *index;
+    }
+
+    /* now that more memory has been reserved, it shouldn't fail */
+    BLI_assert_unreachable();
+    return Index::invalid();
+  }
+
   std::optional<T> remove(Index index)
   {
     if (index.index >= this->data.size()) {
diff --git a/source/blender/blenlib/tests/BLI_generational_arena_test.cc b/source/blender/blenlib/tests/BLI_generational_arena_test.cc
index e677b293434..ead72f80f35 100644
--- a/source/blender/blenlib/tests/BLI_generational_arena_test.cc
+++ b/source/blender/blenlib/tests/BLI_generational_arena_test.cc
@@ -2,6 +2,9 @@
 
 #include "testing/testing.h"
 
+#include <functional>
+#include <tuple>
+
 namespace blender::tests {
 
 using namespace blender::generational_arena;
@@ -56,6 +59,24 @@ TEST(generational_arena, Insert2)
   EXPECT_EQ(arena.get(i5), 5);
 }
 
+TEST(generational_arena, InsertWith)
+{
+  Arena<std::tuple<Index, int>> arena;
+  auto i0 = arena.insert_with([](Index index) { return std::make_tuple(index, 0); });
+  auto i1 = arena.insert_with([](Index index) { return std::make_tuple(index, 1); });
+  auto i2 = arena.insert_with([](Index index) { return std::make_tuple(index, 2); });
+  auto i3 = arena.insert_with([](Index index) { return std::make_tuple(index, 3); });
+  auto i4 = arena.insert_with([](Index index) { return std::make_tuple(index, 4); });
+
+  EXPECT_EQ(arena.capacity(), 8);
+  EXPECT_EQ(arena.size(), 5);
+  EXPECT_EQ(arena.get(i0).value().get(), std::make_tuple(i0, 0));
+  EXPECT_EQ(arena.get(i1).value().get(), std::make_tuple(i1, 1));
+  EXPECT_EQ(arena.get(i2).value().get(), std::make_tuple(i2, 2));
+  EXPECT_EQ(arena.get(i3).value().get(), std::make_tuple(i3, 3));
+  EXPECT_EQ(arena.get(i4).value().get(), std::make_tuple(i4, 4));
+}
+
 TEST(generational_arena, Remove)
 {
   Arena<int> arena(3);



More information about the Bf-blender-cvs mailing list