[Bf-blender-cvs] [556691b19ad] functions: Improve error handling with ValueOrError class

Jacques Lucke noreply at git.blender.org
Wed Jul 24 19:11:21 CEST 2019


Commit: 556691b19ad0b6c3103a721a497b8d84ec452de2
Author: Jacques Lucke
Date:   Wed Jul 24 10:58:11 2019 +0200
Branches: functions
https://developer.blender.org/rB556691b19ad0b6c3103a721a497b8d84ec452de2

Improve error handling with ValueOrError class

We might want to use exceptions instead of this.
I'm not sure yet.

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

M	source/blender/blenlib/BLI_optional.hpp
A	source/blender/blenlib/BLI_value_or_error.hpp
M	source/blender/functions/frontends/data_flow_nodes/data_flow_nodes-c.cpp
M	source/blender/functions/frontends/data_flow_nodes/function_generation.cpp
M	source/blender/functions/frontends/data_flow_nodes/function_generation.hpp
M	source/blender/functions/frontends/data_flow_nodes/graph_generation.cpp
M	source/blender/functions/frontends/data_flow_nodes/graph_generation.hpp
M	source/blender/functions/frontends/data_flow_nodes/inserters/nodes.cpp
M	source/blender/simulations/bparticles/inserters.cpp
M	source/blender/simulations/bparticles/node_frontend.cpp
M	tests/gtests/blenlib/BLI_optional_test.cc

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

diff --git a/source/blender/blenlib/BLI_optional.hpp b/source/blender/blenlib/BLI_optional.hpp
index 904fa153e1e..0365c1772b4 100644
--- a/source/blender/blenlib/BLI_optional.hpp
+++ b/source/blender/blenlib/BLI_optional.hpp
@@ -134,6 +134,14 @@ template<typename T> class Optional {
     }
   }
 
+  T extract()
+  {
+    BLI_assert(m_set);
+    T value = std::move(this->value());
+    this->reset();
+    return value;
+  }
+
  private:
   T *value_ptr() const
   {
diff --git a/source/blender/blenlib/BLI_value_or_error.hpp b/source/blender/blenlib/BLI_value_or_error.hpp
new file mode 100644
index 00000000000..ce2ef066f42
--- /dev/null
+++ b/source/blender/blenlib/BLI_value_or_error.hpp
@@ -0,0 +1,66 @@
+#pragma once
+
+#include "BLI_optional.hpp"
+
+namespace BLI {
+
+struct ErrorInfo {
+  const char *file;
+  uint line;
+  const char *function;
+  std::string message;
+};
+
+/**
+ * This class can be used as return value of functions that might have an error.
+ * The main reason it exists, is that I'm not sure whether we should use exceptions or not. That
+ * needs to be discussed at some point.
+ */
+template<typename T> class ValueOrError {
+ private:
+  Optional<T> m_value;
+  ErrorInfo m_error;
+
+ public:
+  ValueOrError(T value) : m_value(std::move(value))
+  {
+  }
+
+  ValueOrError(ErrorInfo error) : m_error(std::move(error))
+  {
+  }
+
+  static ValueOrError FromError(const char *file,
+                                uint line,
+                                const char *function,
+                                std::string message)
+  {
+    return ValueOrError(ErrorInfo{file, line, function, message});
+  }
+
+  bool is_error() const
+  {
+    return !m_value.has_value();
+  }
+
+  T extract_value()
+  {
+    BLI_assert(m_value.has_value());
+    return m_value.extract();
+  }
+
+  ErrorInfo &error()
+  {
+    return m_error;
+  }
+};
+
+}  // namespace BLI
+
+#define BLI_ERROR_CREATE(MESSAGE) \
+  { \
+    ErrorInfo \
+    { \
+      __FILE__, __LINE__, __func__, MESSAGE \
+    } \
+  }
diff --git a/source/blender/functions/frontends/data_flow_nodes/data_flow_nodes-c.cpp b/source/blender/functions/frontends/data_flow_nodes/data_flow_nodes-c.cpp
index c40276a0822..a1b38da6c4d 100644
--- a/source/blender/functions/frontends/data_flow_nodes/data_flow_nodes-c.cpp
+++ b/source/blender/functions/frontends/data_flow_nodes/data_flow_nodes-c.cpp
@@ -7,12 +7,13 @@ FnFunction FN_tree_to_function(bNodeTree *btree)
 {
   SCOPED_TIMER("Tree to function");
   BLI_assert(btree);
-  auto fn_opt = DataFlowNodes::generate_function(btree);
-  if (!fn_opt.has_value()) {
+  ValueOrError<SharedFunction> fn_or_error = DataFlowNodes::generate_function(btree);
+  if (fn_or_error.is_error()) {
     return nullptr;
   }
 
-  Function *fn_ptr = fn_opt.value().ptr();
+  SharedFunction fn = fn_or_error.extract_value();
+  Function *fn_ptr = fn.ptr();
   fn_ptr->incref();
   return wrap(fn_ptr);
 }
diff --git a/source/blender/functions/frontends/data_flow_nodes/function_generation.cpp b/source/blender/functions/frontends/data_flow_nodes/function_generation.cpp
index c46cca39730..91003b0c4a5 100644
--- a/source/blender/functions/frontends/data_flow_nodes/function_generation.cpp
+++ b/source/blender/functions/frontends/data_flow_nodes/function_generation.cpp
@@ -32,14 +32,14 @@ static void find_interface_sockets(VirtualNodeTree &vtree,
   }
 }
 
-static Optional<FunctionGraph> generate_function_graph(VirtualNodeTree &vtree)
+static ValueOrError<FunctionGraph> generate_function_graph(VirtualNodeTree &vtree)
 {
-  Optional<VTreeDataGraph> data_graph_ = generate_graph(vtree);
-  if (!data_graph_.has_value()) {
-    return {};
+  ValueOrError<VTreeDataGraph> data_graph_or_error = generate_graph(vtree);
+  if (data_graph_or_error.is_error()) {
+    return data_graph_or_error.error();
   }
 
-  VTreeDataGraph &data_graph = data_graph_.value();
+  VTreeDataGraph data_graph = data_graph_or_error.extract_value();
 
   DFGraphSocketSetVector input_sockets;
   DFGraphSocketSetVector output_sockets;
@@ -48,18 +48,18 @@ static Optional<FunctionGraph> generate_function_graph(VirtualNodeTree &vtree)
   return FunctionGraph(data_graph.graph(), input_sockets, output_sockets);
 }
 
-Optional<SharedFunction> generate_function(bNodeTree *btree)
+ValueOrError<SharedFunction> generate_function(bNodeTree *btree)
 {
   VirtualNodeTree vtree;
   vtree.add_all_of_tree(btree);
   vtree.freeze_and_index();
 
-  Optional<FunctionGraph> fgraph_ = generate_function_graph(vtree);
-  if (!fgraph_.has_value()) {
-    return {};
+  ValueOrError<FunctionGraph> fgraph_or_error = generate_function_graph(vtree);
+  if (fgraph_or_error.is_error()) {
+    return fgraph_or_error.error();
   }
 
-  FunctionGraph fgraph = fgraph_.value();
+  FunctionGraph fgraph = fgraph_or_error.extract_value();
   // fgraph.graph()->to_dot__clipboard();
 
   auto fn = fgraph.new_function(btree->id.name);
diff --git a/source/blender/functions/frontends/data_flow_nodes/function_generation.hpp b/source/blender/functions/frontends/data_flow_nodes/function_generation.hpp
index b0b402f2094..f483aff0e70 100644
--- a/source/blender/functions/frontends/data_flow_nodes/function_generation.hpp
+++ b/source/blender/functions/frontends/data_flow_nodes/function_generation.hpp
@@ -1,14 +1,16 @@
 #pragma once
 
 #include "FN_core.hpp"
-#include "BLI_optional.hpp"
+#include "BLI_value_or_error.hpp"
 
 struct bNodeTree;
 
 namespace FN {
 namespace DataFlowNodes {
 
-Optional<SharedFunction> generate_function(struct bNodeTree *btree);
+using BLI::ValueOrError;
+
+ValueOrError<SharedFunction> generate_function(struct bNodeTree *btree);
 
 }  // namespace DataFlowNodes
 }  // namespace FN
diff --git a/source/blender/functions/frontends/data_flow_nodes/graph_generation.cpp b/source/blender/functions/frontends/data_flow_nodes/graph_generation.cpp
index 37d848ff5c3..6e98e2987bc 100644
--- a/source/blender/functions/frontends/data_flow_nodes/graph_generation.cpp
+++ b/source/blender/functions/frontends/data_flow_nodes/graph_generation.cpp
@@ -120,7 +120,7 @@ class BasicUnlinkedInputsHandler : public UnlinkedInputsHandler {
   }
 };
 
-Optional<VTreeDataGraph> generate_graph(VirtualNodeTree &vtree)
+ValueOrError<VTreeDataGraph> generate_graph(VirtualNodeTree &vtree)
 {
   DataFlowGraphBuilder graph_builder;
   Map<VirtualSocket *, DFGB_Socket> socket_map;
@@ -129,11 +129,11 @@ Optional<VTreeDataGraph> generate_graph(VirtualNodeTree &vtree)
   GraphInserters &inserters = get_standard_inserters();
 
   if (!insert_functions_for_bnodes(builder, inserters)) {
-    return {};
+    return BLI_ERROR_CREATE("error inserting functions for nodes");
   }
 
   if (!insert_links(builder, inserters)) {
-    return {};
+    return BLI_ERROR_CREATE("error inserting links");
   }
 
   BasicUnlinkedInputsHandler unlinked_inputs_handler(inserters);
diff --git a/source/blender/functions/frontends/data_flow_nodes/graph_generation.hpp b/source/blender/functions/frontends/data_flow_nodes/graph_generation.hpp
index ec0d36a1709..5411614081b 100644
--- a/source/blender/functions/frontends/data_flow_nodes/graph_generation.hpp
+++ b/source/blender/functions/frontends/data_flow_nodes/graph_generation.hpp
@@ -1,7 +1,7 @@
 #pragma once
 
 #include "FN_core.hpp"
-#include "BLI_optional.hpp"
+#include "BLI_value_or_error.hpp"
 #include "BKE_node_tree.hpp"
 
 #include "builder.hpp"
@@ -12,6 +12,7 @@ namespace DataFlowNodes {
 using BKE::VirtualNode;
 using BKE::VirtualNodeTree;
 using BKE::VirtualSocket;
+using BLI::ValueOrError;
 
 class UnlinkedInputsHandler {
  public:
@@ -69,7 +70,7 @@ class VNodePlaceholderBody : public FunctionBody {
   }
 };
 
-Optional<VTreeDataGraph> generate_graph(VirtualNodeTree &vtree);
+ValueOrError<VTreeDataGraph> generate_graph(VirtualNodeTree &vtree);
 
 }  // namespace DataFlowNodes
 }  // namespace FN
diff --git a/source/blender/functions/frontends/data_flow_nodes/inserters/nodes.cpp b/source/blender/functions/frontends/data_flow_nodes/inserters/nodes.cpp
index fda93632fc2..cbdf0364373 100644
--- a/source/blender/functions/frontends/data_flow_nodes/inserters/nodes.cpp
+++ b/source/blender/functions/frontends/data_flow_nodes/inserters/nodes.cpp
@@ -225,9 +225,10 @@ static void INSERT_call(BTreeGraphBuilder &builder, VirtualNode *vnode)
     return;
   }
 
-  Optional<SharedFunction> fn = generate_function(btree);
-  BLI_assert(fn.has_value());
-  builder.insert_matching_function(fn.value(), vnode);
+  ValueOrError<SharedFunction> fn_or_error = generate_function(btree);
+  BLI_assert(!fn_or_error.is_error());
+  SharedFunction fn = fn_or_error.extract_value();
+  builder.insert_matching_function(fn, vnode);
 }
 
 static void INSERT_switch(BTreeGraphBuilder &builder, VirtualNode *vnode)
diff --git a/source/blender/simulations/bparticles/inserters.cpp b/source/blender/simulations/bparticles/inserters.cpp
index 8bd96771f9f..7aeb64bc687 100644
--- a/source/blender/simulations/bparticles/inserters.cpp
+++ b/source/blender/simulations/bparticles/inserters.cpp
@@ -18,6 +18,7 @@
 
 namespace BParticles {
 
+using BLI::ValueOrError;
 using FN::DFGraphSocket;
 using FN::SharedFunction;
 using FN::SharedType;
@@ -335,11 +336,11 @@ static std::unique_ptr<Emitter> BUILD_EMITTER_custom_function(BuildContext &ctx,
     return {};
   }
 
-  Optional<SharedFunction> fn_emitter_ = FN::DataFlowNodes::generate_function(btree);
-  if (!fn_emitter_.has_value()) {
+  ValueOrError<SharedFunction> fn_emitter_or_error = FN::DataFlowNodes::generate_function(btree);
+  if (fn_emitter_or_error.is_error()) {
     return {};
   }
-  SharedFunction fn_emitter = fn_emitter_.value();
+  SharedFunction fn_emitter = fn_emitter_or_error.extract_value();
 
   SharedFunction fn_inputs = create_function_for_data_inputs(vnode, ctx.data_graph);
 
diff --git a/source/blender/simulations/bparticles/node_frontend.cpp b/source/blender/simulations/bparticles/node_frontend.cpp
index 9f3ade60882..5ff33b561a6 100644
--- a/source/blender/simulations/bparticles/node_frontend.cpp
+++ b/source/blender/simulations/bparticles/node_frontend.cpp
@@ -8,6 +8,7 @@
 namespace BParticles {
 
 using BLI::MultiMap;
+using BLI::ValueOrError;
 
 static bool is_particle_type_node(VirtualNode *vnode)
 {
@@ -54,7 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list