[PPL-devel] [GIT] ppl/ppl(pip): Improved exception safety in method PIP_Solution_Node:: solve().

Enea Zaffanella zaffanella at cs.unipr.it
Sat Feb 6 14:38:26 CET 2010


Module: ppl/ppl
Branch: pip
Commit: 543d508d1069e2c910427abb8563c739c83adaf1
URL:    http://www.cs.unipr.it/git/gitweb.cgi?p=ppl/ppl.git;a=commit;h=543d508d1069e2c910427abb8563c739c83adaf1

Author: Enea Zaffanella <zaffanella at cs.unipr.it>
Date:   Sat Feb  6 14:37:30 2010 +0100

Improved exception safety in method PIP_Solution_Node::solve().

---

 src/PIP_Tree.cc |   50 +++++++++++++++++++++++++++++++-------------------
 1 files changed, 31 insertions(+), 19 deletions(-)

diff --git a/src/PIP_Tree.cc b/src/PIP_Tree.cc
index b179e00..29cc047 100644
--- a/src/PIP_Tree.cc
+++ b/src/PIP_Tree.cc
@@ -25,6 +25,7 @@ site: http://www.cs.unipr.it/ppl/ . */
 #include "PIP_Problem.defs.hh"
 
 #include <algorithm>
+#include <memory>
 
 namespace Parma_Polyhedra_Library {
 
@@ -1882,26 +1883,28 @@ PIP_Solution_Node::solve(const PIP_Problem& problem,
 #endif // #ifdef NOISY_PIP
 
       // Create a solution node for the "true" version of current node.
-      // FIXME: this is not exception safe.
       PIP_Tree_Node* t_node = new PIP_Solution_Node(*this, No_Constraints());
-      context.add_row(t_test);
+      // Protect it from exception safety issues via std::auto_ptr.
+      std::auto_ptr<PIP_Tree_Node> wrapped_node(t_node);
 
-      // Recusively solve true node.
+      // Add parametric constraint to context.
+      context.add_row(t_test);
+      // Recusively solve true node wrt updated context.
       t_node = t_node->solve(problem, context, parameters, space_dim);
 
-      // Modify *this in place to become "false" version of current node.
+      // Modify *this in place to become the "false" version of current node.
       PIP_Tree_Node* f_node = this;
       // Swap aside constraints and artificial parameters
-      // (these could be later restored if needed).
+      // (these will be later restored if needed).
       Constraint_System cs;
       Artificial_Parameter_Sequence aps;
-      cs.swap(constraints_);
-      aps.swap(artificial_parameters);
-      // Negate the condition constraint used for the "true" node.
+      cs.swap(f_node->constraints_);
+      aps.swap(f_node->artificial_parameters);
+      // Compute the complement of the constraint used for the "true" node.
       Row& f_test = context[context.num_rows()-1];
       complement_assign(f_test, t_test, 1);
 
-      // Recusively solve false node.
+      // Recusively solve false node wrt updated context.
       f_node = f_node->solve(problem, context, parameters, space_dim);
 
       // Case analysis on recursive resolution calls outcome.
@@ -1912,13 +1915,13 @@ PIP_Solution_Node::solve(const PIP_Problem& problem,
         }
         else {
           // t_node unfeasible, f_node feasible:
-          // restore cs and aps into *this.
-          constraints_.swap(cs);
-          artificial_parameters.swap(aps);
-          // Add f_test to constraints.
-          add_constraint(f_test, parameters);
+          // restore cs and aps into f_node (i.e., this).
           PPL_ASSERT(f_node == this);
-          return this;
+          f_node->constraints_.swap(cs);
+          f_node->artificial_parameters.swap(aps);
+          // Add f_test to constraints.
+          f_node->add_constraint(f_test, parameters);
+          return f_node;
         }
       }
       else if (f_node == 0) {
@@ -1928,23 +1931,32 @@ PIP_Solution_Node::solve(const PIP_Problem& problem,
         t_node->artificial_parameters.swap(aps);
         // Add t_test to t_nodes's constraints.
         t_node->add_constraint(t_test, parameters);
-        return t_node;
+        // It is now safe to release previously wrapped t_node pointer
+        // and return it to caller.
+        return wrapped_node.release();
       }
 
       // Here both t_node and f_node are feasible:
       // create a new decision node.
-      // FIXME: this is not exception safe.
-      PIP_Decision_Node* parent = new PIP_Decision_Node(f_node, t_node);
+      PIP_Tree_Node* parent = new PIP_Decision_Node(f_node, t_node);
+      // Protect 'parent' from exception safety issues
+      // (previously wrapped t_node is now safe).
+      wrapped_node.release();
+      wrapped_node = std::auto_ptr<PIP_Tree_Node>(parent);
+
+      // Add t_test to the constraints of the new decision node.
       parent->add_constraint(t_test, parameters);
 
       if (!cs.empty()) {
         // If node to be solved had tautologies,
         // store them in a new decision node.
-        // FIXME: this is not exception safe.
+        // NOTE: this is exception safe.
         parent = new PIP_Decision_Node(0, parent);
         parent->constraints_.swap(cs);
       }
       parent->artificial_parameters.swap(aps);
+      // It is now safe to release previously wrapped decision node.
+      wrapped_node.release();
       return parent;
     } // if (first_mixed != not_a_dim)
 




More information about the PPL-devel mailing list