[Bf-blender-cvs] [f19e83f3473] virtual-array-attributes: add typed mutable virtual array

Jacques Lucke noreply at git.blender.org
Mon Apr 12 18:27:52 CEST 2021


Commit: f19e83f34739388080d084014d33083775ef48b7
Author: Jacques Lucke
Date:   Sat Apr 10 14:11:29 2021 +0200
Branches: virtual-array-attributes
https://developer.blender.org/rBf19e83f34739388080d084014d33083775ef48b7

add typed mutable virtual array

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

M	source/blender/blenlib/BLI_virtual_array.hh

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

diff --git a/source/blender/blenlib/BLI_virtual_array.hh b/source/blender/blenlib/BLI_virtual_array.hh
index 71d1699d20d..b585f4e808d 100644
--- a/source/blender/blenlib/BLI_virtual_array.hh
+++ b/source/blender/blenlib/BLI_virtual_array.hh
@@ -194,6 +194,50 @@ template<typename T> class VArray {
   }
 };
 
+template<typename T> class VMutableArray : public VArray<T> {
+ public:
+  VMutableArray(const int64_t size) : VArray<T>(size)
+  {
+  }
+
+  void set(const int64_t index, T value)
+  {
+    BLI_assert(index >= 0);
+    BLI_assert(index < this->size_);
+    this->set_impl(index, std::move(value));
+  }
+
+  void set_all(Span<T> src)
+  {
+    BLI_assert(src.size() == this->size_);
+    this->set_all_impl(src);
+  }
+
+  MutableSpan<T> get_span()
+  {
+    BLI_assert(this->is_span());
+    Span<T> span = static_cast<const VArray<T> *>(this)->get_span();
+    return MutableSpan<T>(const_cast<T *>(span.data()), span.size());
+  }
+
+ protected:
+  virtual void set_impl(const int64_t index, T value) = 0;
+
+  virtual void set_all_impl(Span<T> src)
+  {
+    if (this->is_span()) {
+      const MutableSpan<T> span = this->get_span();
+      initialized_copy_n(src.data(), this->size_, span.data());
+    }
+    else {
+      const int64_t size = this->size_;
+      for (int64_t i = 0; i < size; i++) {
+        this->set(i, src[i]);
+      }
+    }
+  }
+};
+
 /**
  * A virtual array implementation for a span. Methods in this class are final so that it can be
  * devirtualized by the compiler in some cases (e.g. when #devirtualize_varray is used).
@@ -235,6 +279,49 @@ template<typename T> class VArrayForSpan : public VArray<T> {
   }
 };
 
+template<typename T> class VMutableArrayForSpan final : public VMutableArray<T> {
+ private:
+  T *data_ = nullptr;
+
+ public:
+  VMutableArrayForSpan(const MutableSpan<T> data)
+      : VMutableArray<T>(data.size()), data_(data.data())
+  {
+  }
+
+  /* When this constructor is used, the #set_span_start method has to be used as well. */
+  VMutableArrayForSpan(const int64_t size) : VMutableArray<T>(size)
+  {
+  }
+
+ protected:
+  /* Can be used when the data pointer is not ready when the constructor is called. */
+  void set_span_start(T *data)
+  {
+    data_ = data;
+  }
+
+  T get_impl(const int64_t index) const override
+  {
+    return data_[index];
+  }
+
+  void set_impl(const int64_t index, T value) override
+  {
+    data_[index] = value;
+  }
+
+  bool is_span_impl() const override
+  {
+    return true;
+  }
+
+  Span<T> get_span_impl() const override
+  {
+    return Span<T>(data_, this->size_);
+  }
+};
+
 /**
  * A variant of `VArrayForSpan` that owns the underlying data.
  * The `Container` type has to implement a `size()` and `data()` method.
@@ -336,6 +423,61 @@ template<typename T> class VArrayAsSpan final : public VArrayForSpan<T> {
   }
 };
 
+template<typename T> class VMutableArrayAsSpan final : public VMutableArrayForSpan<T> {
+ private:
+  VMutableArray<T> &varray_;
+  Array<T> owned_data_;
+  bool apply_has_been_called_ = false;
+  bool show_not_applied_warning_ = true;
+
+ public:
+  VMutableArrayAsSpan(VMutableArray<T> &varray) : VMutableArrayForSpan<T>(varray.size())
+  {
+    if (varray_.is_span()) {
+      this->set_span_start(varray_.get_span().data());
+    }
+    else {
+      owned_data_.~Array();
+      new (&owned_data_) Array<T>(varray_.size(), NoInitialization{});
+      varray_.materialize_to_uninitialized(owned_data_);
+      this->set_span_start(owned_data_.data());
+    }
+  }
+
+  void disable_not_applied_warning()
+  {
+    show_not_applied_warning_ = false;
+  }
+
+  ~VMutableArrayAsSpan()
+  {
+    if (show_not_applied_warning_) {
+      if (!apply_has_been_called_) {
+        std::cout << "Warning: Call `apply()` to make sure that changes persist in all cases.\n";
+      }
+    }
+  }
+
+  void apply()
+  {
+    apply_has_been_called_ = true;
+    if (this->data_ != owned_data_.data()) {
+      return;
+    }
+    this->set_all(owned_data_);
+  }
+
+  Span<T> as_span() const
+  {
+    return this->get_span();
+  }
+
+  operator Span<T>() const
+  {
+    return this->get_span();
+  }
+};
+
 /**
  * This class makes it easy to create a virtual array for an existing function or lambda. The
  * `GetFunc` should take a single `index` argument and return the value at that index.



More information about the Bf-blender-cvs mailing list