Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <jacques@blender.org>2022-07-21 13:47:44 +0300
committerJacques Lucke <jacques@blender.org>2022-07-21 13:47:44 +0300
commit2034e8c42dd9c09952196fb12a82adde696ac05d (patch)
tree113602b674448c21c92c7687e9695979ecc75913 /source/blender/blenkernel/intern/attribute_access.cc
parent538da79c6d17a6e660a9484c280220240b306282 (diff)
Geometry Nodes: add debug check for whether AttributeWriter.finish is called
Calling `finish` after writing to generic attributes is currently necessary for correctness. Previously, this was easy to forget. Now there is a check for this in debug builds.
Diffstat (limited to 'source/blender/blenkernel/intern/attribute_access.cc')
-rw-r--r--source/blender/blenkernel/intern/attribute_access.cc43
1 files changed, 43 insertions, 0 deletions
diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index b2ac15a71d7..19faddc5727 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -968,6 +968,49 @@ void MutableAttributeAccessor::remove_anonymous()
}
}
+/**
+ * Debug utility that checks whether the #finish function of an #AttributeWriter has been called.
+ */
+#ifdef DEBUG
+struct FinishCallChecker {
+ std::string name;
+ bool finish_called = false;
+ std::function<void()> real_finish_fn;
+
+ ~FinishCallChecker()
+ {
+ if (!this->finish_called) {
+ std::cerr << "Forgot to call `finish()` for '" << this->name << "'.\n";
+ }
+ }
+};
+#endif
+
+GAttributeWriter MutableAttributeAccessor::lookup_for_write(const AttributeIDRef &attribute_id)
+{
+ GAttributeWriter attribute = fn_->lookup_for_write(owner_, attribute_id);
+ /* Check that the #finish method is called in debug builds. */
+#ifdef DEBUG
+ if (attribute) {
+ auto checker = std::make_shared<FinishCallChecker>();
+ if (attribute_id.is_named()) {
+ checker->name = attribute_id.name();
+ }
+ else {
+ checker->name = BKE_anonymous_attribute_id_debug_name(&attribute_id.anonymous_id());
+ }
+ checker->real_finish_fn = attribute.tag_modified_fn;
+ attribute.tag_modified_fn = [checker]() {
+ if (checker->real_finish_fn) {
+ checker->real_finish_fn();
+ }
+ checker->finish_called = true;
+ };
+ }
+#endif
+ return attribute;
+}
+
GAttributeWriter MutableAttributeAccessor::lookup_or_add_for_write(
const AttributeIDRef &attribute_id,
const eAttrDomain domain,