Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r81438 - in sandbox-branches/geometry/index_dev/boost/geometry/extensions/index: . rtree/linear rtree/quadratic rtree/rstar rtree/visitors
From: adam.wulkiewicz_at_[hidden]
Date: 2012-11-20 12:00:42


Author: awulkiew
Date: 2012-11-20 12:00:41 EST (Tue, 20 Nov 2012)
New Revision: 81438
URL: http://svn.boost.org/trac/boost/changeset/81438

Log:
Fixed memleak for CoordinateType/BoundingObject which have throwing copy constructor for R*tree.
Added comments regarding exception-safety.
Text files modified:
   sandbox-branches/geometry/index_dev/boost/geometry/extensions/index/nonassignable.hpp | 2
   sandbox-branches/geometry/index_dev/boost/geometry/extensions/index/pushable_array.hpp | 2 +
   sandbox-branches/geometry/index_dev/boost/geometry/extensions/index/rtree/linear/redistribute_elements.hpp | 16 +++++++-------
   sandbox-branches/geometry/index_dev/boost/geometry/extensions/index/rtree/quadratic/redistribute_elements.hpp | 24 ++++++++++----------
   sandbox-branches/geometry/index_dev/boost/geometry/extensions/index/rtree/rstar/redistribute_elements.hpp | 44 ++++++++++++++++++++-------------------
   sandbox-branches/geometry/index_dev/boost/geometry/extensions/index/rtree/visitors/insert.hpp | 42 ++++++++++++++++++++------------------
   6 files changed, 68 insertions(+), 62 deletions(-)

Modified: sandbox-branches/geometry/index_dev/boost/geometry/extensions/index/nonassignable.hpp
==============================================================================
--- sandbox-branches/geometry/index_dev/boost/geometry/extensions/index/nonassignable.hpp (original)
+++ sandbox-branches/geometry/index_dev/boost/geometry/extensions/index/nonassignable.hpp 2012-11-20 12:00:41 EST (Tue, 20 Nov 2012)
@@ -1,6 +1,6 @@
 // Boost.Geometry Index
 //
-// Spatial query predicates
+// Nonassignable base class.
 //
 // Copyright (c) 2011-2012 Adam Wulkiewicz, Lodz, Poland.
 //

Modified: sandbox-branches/geometry/index_dev/boost/geometry/extensions/index/pushable_array.hpp
==============================================================================
--- sandbox-branches/geometry/index_dev/boost/geometry/extensions/index/pushable_array.hpp (original)
+++ sandbox-branches/geometry/index_dev/boost/geometry/extensions/index/pushable_array.hpp 2012-11-20 12:00:41 EST (Tue, 20 Nov 2012)
@@ -133,6 +133,8 @@
         m_size = 0;
     }
 
+ // IMPORTANT!
+ // The sequence of elements is NOT preserved
     inline void erase(iterator it)
     {
         BOOST_GEOMETRY_INDEX_ASSERT(0 < m_size, "there are no elements in the container");

Modified: sandbox-branches/geometry/index_dev/boost/geometry/extensions/index/rtree/linear/redistribute_elements.hpp
==============================================================================
--- sandbox-branches/geometry/index_dev/boost/geometry/extensions/index/rtree/linear/redistribute_elements.hpp (original)
+++ sandbox-branches/geometry/index_dev/boost/geometry/extensions/index/rtree/linear/redistribute_elements.hpp 2012-11-20 12:00:41 EST (Tue, 20 Nov 2012)
@@ -224,7 +224,7 @@
                 BOOST_GEOMETRY_INDEX_ASSERT(elements1.size() == elements1_count, "unexpected number of elements");
 
                 // copy original elements
- elements_type elements_copy(elements1); // MAY THROW
+ elements_type elements_copy(elements1); // MAY THROW, STRONG (alloc, copy)
 
         // calculate initial seeds
         size_t seed1 = 0;
@@ -242,8 +242,8 @@
         try
         {
             // add seeds
- elements1.push_back(elements_copy[seed1]); // MAY THROW
- elements2.push_back(elements_copy[seed2]); // MAY THROW
+ elements1.push_back(elements_copy[seed1]); // MAY THROW, STRONG (copy)
+ elements2.push_back(elements_copy[seed2]); // MAY THROW, STRONG (alloc, copy)
 
             // calculate boxes
             geometry::convert(rtree::element_indexable(elements_copy[seed1], translator), box1);
@@ -268,13 +268,13 @@
                     // just insert them to this node
                     if ( elements1.size() + remaining <= parameters.get_min_elements() )
                     {
- elements1.push_back(elem); // MAY THROW
+ elements1.push_back(elem); // MAY THROW, STRONG (copy)
                         geometry::expand(box1, indexable);
                         content1 = index::content(box1);
                     }
                     else if ( elements2.size() + remaining <= parameters.get_min_elements() )
                     {
- elements2.push_back(elem); // MAY THROW
+ elements2.push_back(elem); // MAY THROW, STRONG (alloc, copy)
                         geometry::expand(box2, indexable);
                         content2 = index::content(box2);
                     }
@@ -297,13 +297,13 @@
                              ( content_increase1 == content_increase2 && content1 < content2 ) ||
                              ( content1 == content2 && elements1.size() <= elements2.size() ) )
                         {
- elements1.push_back(elem); // MAY THROW
+ elements1.push_back(elem); // MAY THROW, STRONG (copy)
                             box1 = enlarged_box1;
                             content1 = enlarged_content1;
                         }
                         else
                         {
- elements2.push_back(elem); // MAY THROW
+ elements2.push_back(elem); // MAY THROW, STRONG (alloc, copy)
                             box2 = enlarged_box2;
                             content2 = enlarged_content2;
                         }
@@ -322,7 +322,7 @@
             rtree::destroy_elements<Value, Options, Translator, Box, Allocators>::apply(elements_copy, allocators);
             //elements_copy.clear();
 
- throw; // RETHROW
+ throw; // RETHROW, BASIC
         }
     }
 };

Modified: sandbox-branches/geometry/index_dev/boost/geometry/extensions/index/rtree/quadratic/redistribute_elements.hpp
==============================================================================
--- sandbox-branches/geometry/index_dev/boost/geometry/extensions/index/rtree/quadratic/redistribute_elements.hpp (original)
+++ sandbox-branches/geometry/index_dev/boost/geometry/extensions/index/rtree/quadratic/redistribute_elements.hpp 2012-11-20 12:00:41 EST (Tue, 20 Nov 2012)
@@ -109,8 +109,8 @@
         BOOST_GEOMETRY_INDEX_ASSERT(elements1.size() == elements1_count, "unexpected elements number");
 
         // copy original elements
- elements_type elements_copy(elements1); // MAY THROW
- elements_type elements_backup(elements1); // MAY THROW
+ elements_type elements_copy(elements1); // MAY THROW, STRONG (alloc, copy)
+ elements_type elements_backup(elements1); // MAY THROW, STRONG (alloc, copy)
         
         // calculate initial seeds
         size_t seed1 = 0;
@@ -129,8 +129,8 @@
         try
         {
             // add seeds
- elements1.push_back(elements_copy[seed1]); // MAY THROW
- elements2.push_back(elements_copy[seed2]); // MAY THROW
+ elements1.push_back(elements_copy[seed1]); // MAY THROW, STRONG (copy)
+ elements2.push_back(elements_copy[seed2]); // MAY THROW, STRONG (alloc, copy)
 
             // calculate boxes
             geometry::convert(rtree::element_indexable(elements_copy[seed1], translator), box1);
@@ -139,13 +139,13 @@
             // remove seeds
             if (seed1 < seed2)
             {
- elements_copy.erase(elements_copy.begin() + seed2); // MAY THROW
- elements_copy.erase(elements_copy.begin() + seed1); // MAY THROW
+ elements_copy.erase(elements_copy.begin() + seed2); // MAY THROW, BASIC (copy)
+ elements_copy.erase(elements_copy.begin() + seed1); // MAY THROW, BASIC (copy)
             }
             else
             {
- elements_copy.erase(elements_copy.begin() + seed1); // MAY THROW
- elements_copy.erase(elements_copy.begin() + seed2); // MAY THROW
+ elements_copy.erase(elements_copy.begin() + seed1); // MAY THROW, BASIC (copy)
+ elements_copy.erase(elements_copy.begin() + seed2); // MAY THROW, BASIC (copy)
             }
 
             // initialize areas
@@ -201,20 +201,20 @@
 
                 if ( insert_into_group1 )
                 {
- elements1.push_back(elem); // MAY THROW
+ elements1.push_back(elem); // MAY THROW, STRONG (copy)
                     geometry::expand(box1, indexable);
                     content1 = index::content(box1);
                 }
                 else
                 {
- elements2.push_back(elem); // MAY THROW
+ elements2.push_back(elem); // MAY THROW, STRONG (alloc, copy)
                     geometry::expand(box2, indexable);
                     content2 = index::content(box2);
                 }
 
                             BOOST_GEOMETRY_INDEX_ASSERT(!elements_copy.empty(), "expected more elements");
                 typename elements_type::iterator el_it_base = el_it.base();
- elements_copy.erase(--el_it_base); // MAY THROW
+ elements_copy.erase(--el_it_base); // MAY THROW, BASIC (copy)
 
                             BOOST_GEOMETRY_INDEX_ASSERT(0 < remaining, "expected more remaining elements");
                 --remaining;
@@ -229,7 +229,7 @@
             rtree::destroy_elements<Value, Options, Translator, Box, Allocators>::apply(elements_backup, allocators);
             //elements_backup.clear();
 
- throw; // RETHROW
+ throw; // RETHROW, BASIC
         }
     }
 

Modified: sandbox-branches/geometry/index_dev/boost/geometry/extensions/index/rtree/rstar/redistribute_elements.hpp
==============================================================================
--- sandbox-branches/geometry/index_dev/boost/geometry/extensions/index/rtree/rstar/redistribute_elements.hpp (original)
+++ sandbox-branches/geometry/index_dev/boost/geometry/extensions/index/rtree/rstar/redistribute_elements.hpp 2012-11-20 12:00:41 EST (Tue, 20 Nov 2012)
@@ -68,11 +68,11 @@
         BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == parameters.get_max_elements() + 1, "wrong number of elements");
 
         // copy elements
- Elements elements_copy(elements); // MAY THROW
+ Elements elements_copy(elements); // MAY THROW, STRONG (alloc, copy)
         
         // sort elements
         element_axis_corner_less<element_type, Translator, Corner, AxisIndex> elements_less(translator);
- std::sort(elements_copy.begin(), elements_copy.end(), elements_less); // MAY THROW
+ std::sort(elements_copy.begin(), elements_copy.end(), elements_less); // MAY THROW, BASIC (copy)
 
         // init outputs
         choosen_index = parameters.get_min_elements();
@@ -135,7 +135,7 @@
         choose_split_axis_and_index_for_corner<Parameters, Box, min_corner, AxisIndex>::
             apply(elements, index1,
                   som1, ovl1, con1,
- parameters, translator); // MAY THROW
+ parameters, translator); // MAY THROW, STRONG
 
         size_t index2 = 0;
         margin_type som2 = 0;
@@ -145,7 +145,7 @@
         choose_split_axis_and_index_for_corner<Parameters, Box, max_corner, AxisIndex>::
             apply(elements, index2,
                   som2, ovl2, con2,
- parameters, translator); // MAY THROW
+ parameters, translator); // MAY THROW, STRONG
 
         sum_of_margins = som1 + som2;
 
@@ -185,7 +185,7 @@
         choose_split_axis_and_index_for_corner<Parameters, Box, min_corner, AxisIndex>::
             apply(elements, choosen_index,
                   sum_of_margins, smallest_overlap, smallest_content,
- parameters, translator); // MAY THROW
+ parameters, translator); // MAY THROW, STRONG
 
         choosen_corner = min_corner;
     }
@@ -215,7 +215,7 @@
         choose_split_axis_and_index<Parameters, Box, Dimension - 1>::
             apply(elements, choosen_axis, choosen_corner, choosen_index,
                   smallest_sum_of_margins, smallest_overlap, smallest_content,
- parameters, translator); // MAY THROW
+ parameters, translator); // MAY THROW, STRONG
 
         margin_type sum_of_margins = 0;
 
@@ -230,7 +230,7 @@
             Box,
             Dimension - 1,
             typename index::traits::tag<element_indexable_type>::type
- >::apply(elements, corner, index, sum_of_margins, overlap_val, content_val, parameters, translator); // MAY THROW
+ >::apply(elements, corner, index, sum_of_margins, overlap_val, content_val, parameters, translator); // MAY THROW, STRONG
 
         if ( sum_of_margins < smallest_sum_of_margins )
         {
@@ -284,7 +284,7 @@
     {
         if ( axis < Dimension - 1 )
         {
- partial_sort<Corner, Dimension - 1>::apply(elements, axis, index, tr); // MAY THROW
+ partial_sort<Corner, Dimension - 1>::apply(elements, axis, index, tr); // MAY THROW, BASIC (copy)
         }
         else
         {
@@ -292,7 +292,7 @@
 
             typedef typename Elements::value_type element_type;
             element_axis_corner_less<element_type, Translator, Corner, Dimension - 1> less(tr);
- std::partial_sort(elements.begin(), elements.begin() + index, elements.end(), less); // MAY THROW
+ std::partial_sort(elements.begin(), elements.begin() + index, elements.end(), less); // MAY THROW, BASIC (copy)
         }
     }
 };
@@ -307,7 +307,7 @@
 
         typedef typename Elements::value_type element_type;
         element_axis_corner_less<element_type, Translator, Corner, 0> less(tr);
- std::partial_sort(elements.begin(), elements.begin() + index, elements.end(), less); // MAY THROW
+ std::partial_sort(elements.begin(), elements.begin() + index, elements.end(), less); // MAY THROW, BASIC (copy)
     }
 };
 
@@ -356,7 +356,7 @@
>::apply(elements1,
                  split_axis, split_corner, split_index,
                  smallest_sum_of_margins, smallest_overlap, smallest_content,
- parameters, translator); // MAY THROW
+ parameters, translator); // MAY THROW, STRONG
 
         // TODO: awulkiew - get rid of following static_casts?
 
@@ -365,23 +365,24 @@
         BOOST_GEOMETRY_INDEX_ASSERT(parameters.get_min_elements() <= split_index && split_index <= parameters.get_max_elements() - parameters.get_min_elements() + 1, "unexpected value");
         
         // copy original elements
- elements_type elements_copy(elements1); // MAY THROW
+ elements_type elements_copy(elements1); // MAY THROW, STRONG
+ elements_type elements_backup(elements1); // MAY THROW, STRONG
 
         // TODO: awulkiew - check if std::partial_sort produces the same result as std::sort
         if ( split_corner == static_cast<size_t>(min_corner) )
             rstar::partial_sort<min_corner, dimension>
- ::apply(elements_copy, split_axis, split_index, translator); // MAY THROW
+ ::apply(elements_copy, split_axis, split_index, translator); // MAY THROW, BASIC (copy)
         else
             rstar::partial_sort<max_corner, dimension>
- ::apply(elements_copy, split_axis, split_index, translator); // MAY THROW
+ ::apply(elements_copy, split_axis, split_index, translator); // MAY THROW, BASIC (copy)
 
         try
         {
             // copy elements to nodes
- elements1.resize(split_index); // MIGHT THROW
- std::copy(elements_copy.begin(), elements_copy.begin() + split_index, elements1.begin()); // MAY THROW
- elements2.resize(parameters.get_max_elements() + 1 - split_index); // MAY THROW
- std::copy(elements_copy.begin() + split_index, elements_copy.end(), elements2.begin()); // MAY THROW
+ elements1.resize(split_index); // SHOULDN'T THROW
+ std::copy(elements_copy.begin(), elements_copy.begin() + split_index, elements1.begin()); // MAY THROW, BASIC
+ elements2.resize(parameters.get_max_elements() + 1 - split_index); // MAY THROW, STRONG
+ std::copy(elements_copy.begin() + split_index, elements_copy.end(), elements2.begin()); // MAY THROW, BASIC
 
             // calculate boxes
             box1 = rtree::elements_box<Box>(elements1.begin(), elements1.end(), translator);
@@ -389,13 +390,14 @@
         }
         catch(...)
         {
+ //elements_copy.clear();
             elements1.clear();
             elements2.clear();
 
- rtree::destroy_elements<Value, Options, Translator, Box, Allocators>::apply(elements_copy, allocators);
- //elements_copy.clear();
+ rtree::destroy_elements<Value, Options, Translator, Box, Allocators>::apply(elements_backup, allocators);
+ //elements_backup.clear();
 
- throw; // RETHROW
+ throw; // RETHROW, BASIC
         }
     }
 };

Modified: sandbox-branches/geometry/index_dev/boost/geometry/extensions/index/rtree/visitors/insert.hpp
==============================================================================
--- sandbox-branches/geometry/index_dev/boost/geometry/extensions/index/rtree/visitors/insert.hpp (original)
+++ sandbox-branches/geometry/index_dev/boost/geometry/extensions/index/rtree/visitors/insert.hpp 2012-11-20 12:00:41 EST (Tue, 20 Nov 2012)
@@ -157,7 +157,7 @@
             Box,
             Allocators,
             typename Options::redistribute_tag
- >::apply(n, n2, n_box, box2, parameters, translator, allocators); // MAY THROW (V: alloc, copy, E: alloc)
+ >::apply(n, n2, n_box, box2, parameters, translator, allocators); // MAY THROW (V, E: alloc, copy, copy)
 
         // check numbers of elements
         BOOST_GEOMETRY_INDEX_ASSERT(parameters.get_min_elements() <= rtree::elements(n).size() &&
@@ -168,7 +168,7 @@
             "unexpected number of elements");
 
         // return the list of newly created nodes (this algorithm returns one)
- additional_nodes.push_back(std::make_pair(box2, second_node.get())); // MAY THROW
+ additional_nodes.push_back(std::make_pair(box2, second_node.get())); // MAY THROW (alloc, copy)
 
         // release the ptr
         second_node.release();
@@ -269,7 +269,7 @@
             rtree::element_indexable(m_element, m_translator));
 
         // next traversing step
- traverse_apply_visitor(visitor, n, choosen_node_index); // MAY THROW (V: alloc, copy, E: alloc, N:alloc)
+ traverse_apply_visitor(visitor, n, choosen_node_index); // MAY THROW, BASIC (V, E: alloc, copy, N:alloc)
     }
 
     // TODO: awulkiew - change post_traverse name to handle_overflow or overflow_treatment?
@@ -284,7 +284,7 @@
         // handle overflow
         if ( m_parameters.get_max_elements() < rtree::elements(n).size() )
         {
- split(n); // MAY THROW (V: alloc, copy, E: alloc, N:alloc)
+ split(n); // MAY THROW, BASIC (V, E: alloc, copy, N:alloc)
         }
     }
 
@@ -298,7 +298,7 @@
         m_traverse_data.move_to_next_level(&n, choosen_node_index);
 
         // next traversing step
- rtree::apply_visitor(visitor, *rtree::elements(n)[choosen_node_index].second); // MAY THROW (V: alloc, copy, E: alloc, N:alloc)
+ rtree::apply_visitor(visitor, *rtree::elements(n)[choosen_node_index].second); // MAY THROW, BASIC (V, E: alloc, copy, N:alloc)
 
         // restore previous traverse inputs
         m_traverse_data = backup_traverse_data;
@@ -314,11 +314,12 @@
         typename split_algo::nodes_container_type additional_nodes;
         Box n_box;
 
- split_algo::apply(additional_nodes, n, n_box, m_parameters, m_translator, m_allocators); // MAY THROW (V: alloc, copy, E: alloc, N:alloc)
+ split_algo::apply(additional_nodes, n, n_box, m_parameters, m_translator, m_allocators); // MAY THROW, BASIC (V, E: alloc, copy, N:alloc)
 
         BOOST_GEOMETRY_INDEX_ASSERT(additional_nodes.size() == 1, "unexpected number of additional nodes");
 
         // TODO add all additional nodes
+ // For kmeans algorithm:
         // elements number may be greater than node max elements count
         // split and reinsert must take node with some elements count
         // and container of additional elements (std::pair<Box, node*>s or Values)
@@ -336,7 +337,7 @@
             // update old node's box
             m_traverse_data.current_element().first = n_box;
             // add new node to parent's children
- m_traverse_data.parent_elements().push_back(additional_nodes[0]); // MAY THROW (V: alloc, copy, E: alloc)
+ m_traverse_data.parent_elements().push_back(additional_nodes[0]); // MAY THROW, STRONG (V, E: alloc, copy)
         }
         // node is the root - add level
         else
@@ -344,15 +345,15 @@
             BOOST_GEOMETRY_INDEX_ASSERT(&n == rtree::get<Node>(m_root_node), "node should be the root");
 
             // create new root and add nodes
- node_auto_ptr new_root(rtree::create_node<Allocators, internal_node>::apply(m_allocators), m_allocators); // MAY THROW (N:alloc)
+ node_auto_ptr new_root(rtree::create_node<Allocators, internal_node>::apply(m_allocators), m_allocators); // MAY THROW, STRONG (N:alloc)
 
             try {
- rtree::elements(rtree::get<internal_node>(*new_root)).push_back(std::make_pair(n_box, m_root_node)); // MAY THROW (E:alloc)
- rtree::elements(rtree::get<internal_node>(*new_root)).push_back(additional_nodes[0]); // MAY THROW (E:alloc)
+ rtree::elements(rtree::get<internal_node>(*new_root)).push_back(std::make_pair(n_box, m_root_node)); // MAY THROW, STRONG (E:alloc, copy)
+ rtree::elements(rtree::get<internal_node>(*new_root)).push_back(additional_nodes[0]); // MAY THROW, STRONG (E:alloc, copy)
             } catch (...) {
                 // clear new root to not delete in the ~node_auto_ptr() potentially stored old root node
                 rtree::elements(rtree::get<internal_node>(*new_root)).clear();
- throw; // RETHROW
+ throw; // RETHROW, BASIC
             }
 
             m_root_node = new_root.get();
@@ -421,7 +422,7 @@
         if ( base::m_traverse_data.current_level < base::m_level )
         {
             // next traversing step
- base::traverse(*this, n); // MAY THROW (E: alloc, N: alloc)
+ base::traverse(*this, n); // MAY THROW, BASIC (E: alloc, copy, N: alloc)
         }
         else
         {
@@ -430,19 +431,20 @@
             try
             {
                 // push new child node
- rtree::elements(n).push_back(base::m_element); // MAY THROW (E: alloc)
+ rtree::elements(n).push_back(base::m_element); // MAY THROW, STRONG (E: alloc, copy)
             }
             catch(...)
             {
- // if the insert fails here, the element won't be stored in the tree
+ // if the insert fails above, the element won't be stored in the tree
+
                 rtree::visitors::destroy<Value, Options, Translator, Box, Allocators> del_v(base::m_element.second, base::m_allocators);
                 rtree::apply_visitor(del_v, *base::m_element.second);
 
- throw; // RETHROW
+ throw; // RETHROW, BASIC
             }
         }
 
- base::post_traverse(n); // MAY THROW (E: alloc, N: alloc)
+ base::post_traverse(n); // MAY THROW, BASIC (E: alloc, copy, N: alloc)
     }
 
     inline void operator()(leaf &)
@@ -481,9 +483,9 @@
         BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_level, "unexpected level");
 
         // next traversing step
- base::traverse(*this, n); // MAY THROW (V: alloc, copy, E: alloc, N: alloc)
+ base::traverse(*this, n); // MAY THROW, BASIC (V, E: alloc, copy, N: alloc)
 
- base::post_traverse(n); // MAY THROW (E: alloc, N: alloc)
+ base::post_traverse(n); // MAY THROW, BASIC (E: alloc, copy, N: alloc)
     }
 
     inline void operator()(leaf & n)
@@ -492,9 +494,9 @@
         BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level ||
                                     base::m_level == (std::numeric_limits<size_t>::max)(), "unexpected level");
         
- rtree::elements(n).push_back(base::m_element); // MAY THROW (V: alloc, copy)
+ rtree::elements(n).push_back(base::m_element); // MAY THROW, STRONG (V: alloc, copy)
 
- base::post_traverse(n); // MAY THROW (V: alloc, copy, E: alloc, N: alloc)
+ base::post_traverse(n); // MAY THROW, BASIC (V: alloc, copy, N: alloc)
     }
 };
 


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk