[Bf-blender-cvs] [c73ae711bf4] master: BLI: new basic CacheMutex

Jacques Lucke noreply at git.blender.org
Tue Nov 8 15:51:05 CET 2022


Commit: c73ae711bf403585de403bcfeb7519dd989d4c15
Author: Jacques Lucke
Date:   Tue Nov 8 15:50:49 2022 +0100
Branches: master
https://developer.blender.org/rBc73ae711bf403585de403bcfeb7519dd989d4c15

BLI: new basic CacheMutex

This patch introduces a new `CacheMutex` which makes it easy to implement
lazily computed caches in e.g. `Curves`. For more details see `BLI_cache_mutex.hh`.

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

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

M	source/blender/blenkernel/BKE_curves.hh
M	source/blender/blenkernel/intern/curves_geometry.cc
A	source/blender/blenlib/BLI_cache_mutex.hh
M	source/blender/blenlib/CMakeLists.txt
A	source/blender/blenlib/intern/cache_mutex.cc

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

diff --git a/source/blender/blenkernel/BKE_curves.hh b/source/blender/blenkernel/BKE_curves.hh
index 4c7ff8c1813..a479dcb574d 100644
--- a/source/blender/blenkernel/BKE_curves.hh
+++ b/source/blender/blenkernel/BKE_curves.hh
@@ -11,6 +11,7 @@
 
 #include <mutex>
 
+#include "BLI_cache_mutex.hh"
 #include "BLI_float3x3.hh"
 #include "BLI_float4x4.hh"
 #include "BLI_generic_virtual_array.hh"
@@ -80,17 +81,14 @@ class CurvesGeometryRuntime {
    */
   mutable Vector<int> evaluated_offsets_cache;
   mutable Vector<int> bezier_evaluated_offsets;
-  mutable std::mutex offsets_cache_mutex;
-  mutable bool offsets_cache_dirty = true;
+  mutable CacheMutex offsets_cache_mutex;
 
   mutable Vector<curves::nurbs::BasisCache> nurbs_basis_cache;
-  mutable std::mutex nurbs_basis_cache_mutex;
-  mutable bool nurbs_basis_cache_dirty = true;
+  mutable CacheMutex nurbs_basis_cache_mutex;
 
   /** Cache of evaluated positions. */
   mutable Vector<float3> evaluated_position_cache;
-  mutable std::mutex position_cache_mutex;
-  mutable bool position_cache_dirty = true;
+  mutable CacheMutex position_cache_mutex;
   /**
    * The evaluated positions result, using a separate span in case all curves are poly curves,
    * in which case a separate array of evaluated positions is unnecessary.
@@ -103,18 +101,15 @@ class CurvesGeometryRuntime {
    * make slicing this array for a curve fast, an extra float is stored for every curve.
    */
   mutable Vector<float> evaluated_length_cache;
-  mutable std::mutex length_cache_mutex;
-  mutable bool length_cache_dirty = true;
+  mutable CacheMutex length_cache_mutex;
 
   /** Direction of the curve at each evaluated point. */
   mutable Vector<float3> evaluated_tangent_cache;
-  mutable std::mutex tangent_cache_mutex;
-  mutable bool tangent_cache_dirty = true;
+  mutable CacheMutex tangent_cache_mutex;
 
   /** Normal direction vectors for each evaluated point. */
   mutable Vector<float3> evaluated_normal_cache;
-  mutable std::mutex normal_cache_mutex;
-  mutable bool normal_cache_dirty = true;
+  mutable CacheMutex normal_cache_mutex;
 };
 
 /**
@@ -909,13 +904,13 @@ inline int CurvesGeometry::evaluated_points_num() const
 
 inline IndexRange CurvesGeometry::evaluated_points_for_curve(int index) const
 {
-  BLI_assert(!this->runtime->offsets_cache_dirty);
+  BLI_assert(this->runtime->offsets_cache_mutex.is_cached());
   return offsets_to_range(this->runtime->evaluated_offsets_cache.as_span(), index);
 }
 
 inline IndexRange CurvesGeometry::evaluated_points_for_curves(const IndexRange curves) const
 {
-  BLI_assert(!this->runtime->offsets_cache_dirty);
+  BLI_assert(this->runtime->offsets_cache_mutex.is_cached());
   BLI_assert(this->curve_num > 0);
   const int offset = this->runtime->evaluated_offsets_cache[curves.start()];
   const int offset_next = this->runtime->evaluated_offsets_cache[curves.one_after_last()];
@@ -940,7 +935,7 @@ inline IndexRange CurvesGeometry::lengths_range_for_curve(const int curve_index,
 inline Span<float> CurvesGeometry::evaluated_lengths_for_curve(const int curve_index,
                                                                const bool cyclic) const
 {
-  BLI_assert(!this->runtime->length_cache_dirty);
+  BLI_assert(this->runtime->length_cache_mutex.is_cached());
   const IndexRange range = this->lengths_range_for_curve(curve_index, cyclic);
   return this->runtime->evaluated_length_cache.as_span().slice(range);
 }
diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc
index 7c338480c71..43bdb8e7b8c 100644
--- a/source/blender/blenkernel/intern/curves_geometry.cc
+++ b/source/blender/blenkernel/intern/curves_geometry.cc
@@ -511,17 +511,7 @@ static void calculate_evaluated_offsets(const CurvesGeometry &curves,
 
 void CurvesGeometry::ensure_evaluated_offsets() const
 {
-  if (!this->runtime->offsets_cache_dirty) {
-    return;
-  }
-
-  /* A double checked lock. */
-  std::scoped_lock lock{this->runtime->offsets_cache_mutex};
-  if (!this->runtime->offsets_cache_dirty) {
-    return;
-  }
-
-  threading::isolate_task([&]() {
+  this->runtime->offsets_cache_mutex.ensure([&]() {
     this->runtime->evaluated_offsets_cache.resize(this->curves_num() + 1);
 
     if (this->has_curve_with_type(CURVE_TYPE_BEZIER)) {
@@ -534,8 +524,6 @@ void CurvesGeometry::ensure_evaluated_offsets() const
     calculate_evaluated_offsets(
         *this, this->runtime->evaluated_offsets_cache, this->runtime->bezier_evaluated_offsets);
   });
-
-  this->runtime->offsets_cache_dirty = false;
 }
 
 Span<int> CurvesGeometry::evaluated_offsets() const
@@ -569,17 +557,7 @@ Array<int> CurvesGeometry::point_to_curve_map() const
 
 void CurvesGeometry::ensure_nurbs_basis_cache() const
 {
-  if (!this->runtime->nurbs_basis_cache_dirty) {
-    return;
-  }
-
-  /* A double checked lock. */
-  std::scoped_lock lock{this->runtime->nurbs_basis_cache_mutex};
-  if (!this->runtime->nurbs_basis_cache_dirty) {
-    return;
-  }
-
-  threading::isolate_task([&]() {
+  this->runtime->nurbs_basis_cache_mutex.ensure([&]() {
     Vector<int64_t> nurbs_indices;
     const IndexMask nurbs_mask = this->indices_for_curve_type(CURVE_TYPE_NURBS, nurbs_indices);
     if (nurbs_mask.is_empty()) {
@@ -619,23 +597,11 @@ void CurvesGeometry::ensure_nurbs_basis_cache() const
       }
     });
   });
-
-  this->runtime->nurbs_basis_cache_dirty = false;
 }
 
 Span<float3> CurvesGeometry::evaluated_positions() const
 {
-  if (!this->runtime->position_cache_dirty) {
-    return this->runtime->evaluated_positions_span;
-  }
-
-  /* A double checked lock. */
-  std::scoped_lock lock{this->runtime->position_cache_mutex};
-  if (!this->runtime->position_cache_dirty) {
-    return this->runtime->evaluated_positions_span;
-  }
-
-  threading::isolate_task([&]() {
+  this->runtime->position_cache_mutex.ensure([&]() {
     if (this->is_single_type(CURVE_TYPE_POLY)) {
       this->runtime->evaluated_positions_span = this->positions();
       this->runtime->evaluated_position_cache.clear_and_make_inline();
@@ -699,24 +665,12 @@ Span<float3> CurvesGeometry::evaluated_positions() const
       }
     });
   });
-
-  this->runtime->position_cache_dirty = false;
   return this->runtime->evaluated_positions_span;
 }
 
 Span<float3> CurvesGeometry::evaluated_tangents() const
 {
-  if (!this->runtime->tangent_cache_dirty) {
-    return this->runtime->evaluated_tangent_cache;
-  }
-
-  /* A double checked lock. */
-  std::scoped_lock lock{this->runtime->tangent_cache_mutex};
-  if (!this->runtime->tangent_cache_dirty) {
-    return this->runtime->evaluated_tangent_cache;
-  }
-
-  threading::isolate_task([&]() {
+  this->runtime->tangent_cache_mutex.ensure([&]() {
     const Span<float3> evaluated_positions = this->evaluated_positions();
     const VArray<bool> cyclic = this->cyclic();
 
@@ -732,9 +686,9 @@ Span<float3> CurvesGeometry::evaluated_tangents() const
       }
     });
 
-    /* Correct the first and last tangents of non-cyclic Bezier curves so that they align with the
-     * inner handles. This is a separate loop to avoid the cost when Bezier type curves are not
-     * used. */
+    /* Correct the first and last tangents of non-cyclic Bezier curves so that they align with
+     * the inner handles. This is a separate loop to avoid the cost when Bezier type curves are
+     * not used. */
     Vector<int64_t> bezier_indices;
     const IndexMask bezier_mask = this->indices_for_curve_type(CURVE_TYPE_BEZIER, bezier_indices);
     if (!bezier_mask.is_empty()) {
@@ -765,8 +719,6 @@ Span<float3> CurvesGeometry::evaluated_tangents() const
       });
     }
   });
-
-  this->runtime->tangent_cache_dirty = false;
   return this->runtime->evaluated_tangent_cache;
 }
 
@@ -781,17 +733,7 @@ static void rotate_directions_around_axes(MutableSpan<float3> directions,
 
 Span<float3> CurvesGeometry::evaluated_normals() const
 {
-  if (!this->runtime->normal_cache_dirty) {
-    return this->runtime->evaluated_normal_cache;
-  }
-
-  /* A double checked lock. */
-  std::scoped_lock lock{this->runtime->normal_cache_mutex};
-  if (!this->runtime->normal_cache_dirty) {
-    return this->runtime->evaluated_normal_cache;
-  }
-
-  threading::isolate_task([&]() {
+  this->runtime->normal_cache_mutex.ensure([&]() {
     const Span<float3> evaluated_tangents = this->evaluated_tangents();
     const VArray<bool> cyclic = this->cyclic();
     const VArray<int8_t> normal_mode = this->normal_mode();
@@ -842,8 +784,6 @@ Span<float3> CurvesGeometry::evaluated_normals() const
       }
     });
   });
-
-  this->runtime->normal_cache_dirty = false;
   return this->runtime->evaluated_normal_cache;
 }
 
@@ -851,8 +791,8 @@ void CurvesGeometry::interpolate_to_evaluated(const int curve_index,
                                               const GSpan src,
                                               GMutableSpan dst) const
 {
-  BLI_assert(!this->runtime->offsets_cache_dirty);
-  BLI_assert(!this->runtime->nurbs_basis_cache_dirty);
+  BLI_assert(this->runtime->offsets_cache_mutex.is_cached());
+  BLI_assert(this->runtime->nurbs_basis_cache_mutex.is_cached());
   const IndexRange points = this->points_for_curve(curve_index);
   BLI_assert(src.size() == points.size());
   BLI_assert(dst.size() == this->evaluated_points_for_curve(curve_index).size());
@@ -881,8 +821,8 @@ void CurvesGeometry::interpolate_to_evaluated(const int curve_index,
 
 void CurvesGeometry::interpolate_to_evaluated(const GSpan src, GMutableSpan dst) const
 {
-  BLI_assert(!this->runtime->offsets_cache_dirty);
-  BLI_assert(!this->runtime->nurbs_basis_cache_dirty);
+  BLI_assert(this->runtime->offsets_cache_mutex.is_cached());
+  BLI_assert(this->runtime->nurbs_basis_cache_mutex.is_cached());
   const VArray<int8_t> types = this->curve_types();
   const VArray<int> resolution = this->resolution();
   const VArray<bool> cyclic = this->cyclic();
@@ -923,17 +863,7 @@ void CurvesGeometry::interpolate_to_evaluated(const GSpan src, GMutableSpan dst)
 
 void CurvesGeometry::ensure_evaluated_lengths() const
 {
-  if (!this->runtime->length_cache_dirty) {
-    return;
-  }
-
-  /* A double checked lock. */
-  std::scoped_lock lock{this->runtime->length_cache_mutex

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list