[Bf-blender-cvs] [a76bb1a2778] master: BLI: Support removing keys from a set during iteration

Hans Goudey noreply at git.blender.org
Tue Oct 19 05:15:59 CEST 2021


Commit: a76bb1a27782317449c04c0ab4916d66c46b6803
Author: Hans Goudey
Date:   Mon Oct 18 22:15:52 2021 -0500
Branches: master
https://developer.blender.org/rBa76bb1a27782317449c04c0ab4916d66c46b6803

BLI: Support removing keys from a set during iteration

This adds the ability to mark slots as removed while iterating through
a mutable set.

Differential Revision: https://developer.blender.org/D12867

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

M	source/blender/blenlib/BLI_set.hh
M	source/blender/blenlib/tests/BLI_set_test.cc

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

diff --git a/source/blender/blenlib/BLI_set.hh b/source/blender/blenlib/BLI_set.hh
index a8ccf957f6c..2e0dfea70e9 100644
--- a/source/blender/blenlib/BLI_set.hh
+++ b/source/blender/blenlib/BLI_set.hh
@@ -423,6 +423,8 @@ class Set {
     int64_t total_slots_;
     int64_t current_slot_;
 
+    friend Set;
+
    public:
     Iterator(const Slot *slots, int64_t total_slots, int64_t current_slot)
         : slots_(slots), total_slots_(total_slots), current_slot_(current_slot)
@@ -467,6 +469,12 @@ class Set {
     {
       return !(a != b);
     }
+
+   protected:
+    const Slot &current_slot() const
+    {
+      return slots_[current_slot_];
+    }
   };
 
   Iterator begin() const
@@ -484,6 +492,20 @@ class Set {
     return Iterator(slots_.data(), slots_.size(), slots_.size());
   }
 
+  /**
+   * Remove the key that the iterator is currently pointing at. It is valid to call this method
+   * while iterating over the set. However, after this method has been called, the removed element
+   * must not be accessed anymore.
+   */
+  void remove(const Iterator &iterator)
+  {
+    /* The const cast is valid because this method itself is not const. */
+    Slot &slot = const_cast<Slot &>(iterator.current_slot());
+    BLI_assert(slot.is_occupied());
+    slot.remove();
+    removed_slots_++;
+  }
+
   /**
    * Print common statistics like size and collision count. This is useful for debugging purposes.
    */
diff --git a/source/blender/blenlib/tests/BLI_set_test.cc b/source/blender/blenlib/tests/BLI_set_test.cc
index 3a4733a218f..28eb4df2ca6 100644
--- a/source/blender/blenlib/tests/BLI_set_test.cc
+++ b/source/blender/blenlib/tests/BLI_set_test.cc
@@ -544,6 +544,32 @@ TEST(set, GenericAlgorithms)
   EXPECT_EQ(std::count(set.begin(), set.end(), 20), 1);
 }
 
+TEST(set, RemoveDuringIteration)
+{
+  Set<int> set;
+  set.add(6);
+  set.add(5);
+  set.add(2);
+  set.add(3);
+
+  EXPECT_EQ(set.size(), 4);
+
+  using Iter = Set<int>::Iterator;
+  Iter begin = set.begin();
+  Iter end = set.end();
+  for (Iter iter = begin; iter != end; ++iter) {
+    int item = *iter;
+    if (item == 2) {
+      set.remove(iter);
+    }
+  }
+
+  EXPECT_EQ(set.size(), 3);
+  EXPECT_TRUE(set.contains(5));
+  EXPECT_TRUE(set.contains(6));
+  EXPECT_TRUE(set.contains(3));
+}
+
 /**
  * Set this to 1 to activate the benchmark. It is disabled by default, because it prints a lot.
  */



More information about the Bf-blender-cvs mailing list