$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r85026 - in trunk/boost/geometry/index: . detail detail/rtree/node
From: adam.wulkiewicz_at_[hidden]
Date: 2013-07-13 21:59:26
Author: awulkiew
Date: 2013-07-13 21:59:26 EDT (Sat, 13 Jul 2013)
New Revision: 85026
URL: http://svn.boost.org/trac/boost/changeset/85026
Log:
[geometry][index]: experimental rtree serialization support added.
Added:
   trunk/boost/geometry/index/detail/serialization.hpp   (contents, props changed)
Text files modified: 
   trunk/boost/geometry/index/detail/rtree/node/node_auto_ptr.hpp |     2                                         
   trunk/boost/geometry/index/detail/serialization.hpp            |   396 ++++++++++++++++++++++++++++++++++++++++
   trunk/boost/geometry/index/rtree.hpp                           |    53 +++++                                   
   3 files changed, 451 insertions(+), 0 deletions(-)
Modified: trunk/boost/geometry/index/detail/rtree/node/node_auto_ptr.hpp
==============================================================================
--- trunk/boost/geometry/index/detail/rtree/node/node_auto_ptr.hpp	Sat Jul 13 14:07:24 2013	(r85025)
+++ trunk/boost/geometry/index/detail/rtree/node/node_auto_ptr.hpp	2013-07-13 21:59:26 EDT (Sat, 13 Jul 2013)	(r85026)
@@ -17,6 +17,8 @@
 
 namespace detail { namespace rtree {
 
+// TODO - change the name to node_scoped_ptr
+
 template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
 class node_auto_ptr
 {
Added: trunk/boost/geometry/index/detail/serialization.hpp
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/boost/geometry/index/detail/serialization.hpp	2013-07-13 21:59:26 EDT (Sat, 13 Jul 2013)	(r85026)
@@ -0,0 +1,396 @@
+// Boost.Geometry Index
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_SERIALIZATION_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_SERIALIZATION_HPP
+
+//#include <boost/serialization/serialization.hpp>
+#include <boost/serialization/split_member.hpp>
+#include <boost/serialization/version.hpp>
+//#include <boost/serialization/nvp.hpp>
+
+// TODO
+// how about using the unsigned type capable of storing Max in compile-time versions?
+
+// TODO - move to index/detail/serialization.hpp
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+// TODO - use boost::move?
+template<typename T>
+class serialization_storage
+{
+public:
+    template <typename Archive>
+    serialization_storage(Archive & ar, unsigned int version)
+    {
+        boost::serialization::load_construct_data_adl(ar, this->address(), version);
+    }
+    ~serialization_storage()
+    {
+        this->address()->~T();
+    }
+    T * address()
+    {
+        return static_cast<T*>(m_storage.address());
+    }
+private:
+    boost::aligned_storage<sizeof(T), boost::alignment_of<T>::value> m_storage;
+};
+
+// TODO - save and load item_version? see: collections_load_imp and collections_save_imp
+// this should be done once for the whole container
+// versions of all used types should be stored
+
+template <typename T, typename Archive> inline
+T serialization_load(Archive & ar)
+{
+    namespace bs = boost::serialization;    
+    serialization_storage<T> storage(ar, bs::version<T>::value);        // load_construct_data
+    //ar >> boost::serialization::make_nvp("name", *storage.address());
+    ar >> *storage.address();                                           // serialize
+    return *storage.address();
+}
+
+template <typename T, typename Archive> inline
+void serialization_save(T const& t, Archive & ar)
+{
+    namespace bs = boost::serialization;
+    bs::save_construct_data_adl(ar, boost::addressof(t), bs::version<T>::value);  // save_construct_data
+    //ar << boost::serialization::make_nvp("name", t);
+    ar << t;                                                                                        // serialize
+}
+    
+}}}}
+
+// TODO - move to index/serialization.hpp
+namespace boost { namespace serialization {
+
+// boost::geometry::index::linear
+
+template<class Archive, size_t Max, size_t Min>
+void save_construct_data(Archive & ar, const boost::geometry::index::linear<Max, Min> * params, unsigned int )
+{
+    size_t max = params->get_max_elements(), min = params->get_min_elements();
+    ar << max << min;
+}
+template<class Archive, size_t Max, size_t Min>
+void load_construct_data(Archive & ar, boost::geometry::index::linear<Max, Min> * params, unsigned int )
+{
+    size_t max, min;
+    ar >> max >> min;
+    if ( max != params->get_max_elements() || min != params->get_min_elements() )
+        // TODO change exception type
+        BOOST_THROW_EXCEPTION(std::runtime_error("parameters not compatible"));
+    // the constructor musn't be called for this type
+    //::new(params)boost::geometry::index::linear<Max, Min>();
+}
+template<class Archive, size_t Max, size_t Min> void serialize(Archive &, boost::geometry::index::linear<Max, Min> &, unsigned int) {}
+
+// boost::geometry::index::quadratic
+
+template<class Archive, size_t Max, size_t Min>
+void save_construct_data(Archive & ar, const boost::geometry::index::quadratic<Max, Min> * params, unsigned int )
+{
+    size_t max = params->get_max_elements(), min = params->get_min_elements();
+    ar << max << min;
+}
+template<class Archive, size_t Max, size_t Min>
+void load_construct_data(Archive & ar, boost::geometry::index::quadratic<Max, Min> * params, unsigned int )
+{
+    size_t max, min;
+    ar >> max >> min;
+    if ( max != params->get_max_elements() || min != params->get_min_elements() )
+        // TODO change exception type
+        BOOST_THROW_EXCEPTION(std::runtime_error("parameters not compatible"));
+    // the constructor musn't be called for this type
+    //::new(params)boost::geometry::index::quadratic<Max, Min>();
+}
+template<class Archive, size_t Max, size_t Min> void serialize(Archive &, boost::geometry::index::quadratic<Max, Min> &, unsigned int) {}
+
+// boost::geometry::index::rstar
+
+template<class Archive, size_t Max, size_t Min, size_t RE, size_t OCT>
+void save_construct_data(Archive & ar, const boost::geometry::index::rstar<Max, Min, RE, OCT> * params, unsigned int )
+{
+    size_t max = params->get_max_elements()
+         , min = params->get_min_elements()
+         , re = params->get_reinserted_elements()
+         , oct = params->get_overlap_cost_threshold();
+    ar << max << min << re << oct;
+}
+template<class Archive, size_t Max, size_t Min, size_t RE, size_t OCT>
+void load_construct_data(Archive & ar, boost::geometry::index::rstar<Max, Min, RE, OCT> * params, unsigned int )
+{
+    size_t max, min, re, oct;
+    ar >> max >> min;
+    if ( max != params->get_max_elements() || min != params->get_min_elements() ||
+         re != params->get_reinserted_elements() || oct != params->get_overlap_cost_threshold() )
+        // TODO change exception type
+        BOOST_THROW_EXCEPTION(std::runtime_error("parameters not compatible"));
+    // the constructor musn't be called for this type
+    //::new(params)boost::geometry::index::rstar<Max, Min, RE, OCT>();
+}
+template<class Archive, size_t Max, size_t Min, size_t RE, size_t OCT>
+void serialize(Archive &, boost::geometry::index::rstar<Max, Min, RE, OCT> &, unsigned int) {}
+
+// boost::geometry::index::dynamic_linear
+
+template<class Archive>
+inline void save_construct_data(Archive & ar, const boost::geometry::index::dynamic_linear * params, unsigned int )
+{
+    size_t max = params->get_max_elements(), min = params->get_min_elements();
+    ar << max << min;
+}
+template<class Archive>
+inline void load_construct_data(Archive & ar, boost::geometry::index::dynamic_linear * params, unsigned int )
+{
+    size_t max, min;
+    ar >> max >> min;
+    ::new(params)boost::geometry::index::dynamic_linear(max, min);
+}
+template<class Archive> void serialize(Archive &, boost::geometry::index::dynamic_linear &, unsigned int) {}
+
+// boost::geometry::index::dynamic_quadratic
+
+template<class Archive>
+inline void save_construct_data(Archive & ar, const boost::geometry::index::dynamic_quadratic * params, unsigned int )
+{
+    size_t max = params->get_max_elements(), min = params->get_min_elements();
+    ar << max << min;
+}
+template<class Archive>
+inline void load_construct_data(Archive & ar, boost::geometry::index::dynamic_quadratic * params, unsigned int )
+{
+    size_t max, min;
+    ar >> max >> min;
+    ::new(params)boost::geometry::index::dynamic_quadratic(max, min);
+}
+template<class Archive> void serialize(Archive &, boost::geometry::index::dynamic_quadratic &, unsigned int) {}
+
+// boost::geometry::index::dynamic_rstar
+
+template<class Archive>
+inline void save_construct_data(Archive & ar, const boost::geometry::index::dynamic_rstar * params, unsigned int )
+{
+    size_t max = params->get_max_elements()
+         , min = params->get_min_elements()
+         , re = params->get_reinserted_elements()
+         , oct = params->get_overlap_cost_threshold();
+    ar << max << min;
+}
+template<class Archive>
+inline void load_construct_data(Archive & ar, boost::geometry::index::dynamic_rstar * params, unsigned int )
+{
+    size_t max, min, re, oct;
+    ar >> max >> min >> re >> oct;
+    ::new(params)boost::geometry::index::dynamic_rstar(max, min, re, oct);
+}
+template<class Archive> void serialize(Archive &, boost::geometry::index::dynamic_rstar &, unsigned int) {}
+
+}} // boost::serialization
+
+// TODO - move to index/detail/serialization.hpp or maybe geometry/serialization.hpp
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+template <typename P, size_t I = 0, size_t D = traits::dimension<P>::value>
+struct serialize_point
+{
+    template <typename Archive>
+    static inline void save(Archive & ar, P const& p, unsigned int version)
+    {
+        typename coordinate_type<P>::type c = get<I>(p);
+        ar << c;
+        serialize_point<P, I+1, D>::save(ar, p, version);
+    }
+
+    template <typename Archive>
+    static inline void load(Archive & ar, P & p, unsigned int version)
+    {
+        typename traits::coordinate_type<P>::type c;
+        ar >> c;
+        set<I>(p, c);
+        serialize_point<P, I+1, D>::load(ar, p, version);
+    }
+};
+
+template <typename P, size_t D>
+struct serialize_point<P, D, D>
+{
+    template <typename Archive> static inline void save(Archive &, P const&, unsigned int) {}
+    template <typename Archive> static inline void load(Archive &, P &, unsigned int) {}
+};
+
+}}}}
+
+// TODO - move to index/detail/serialization.hpp or maybe geometry/serialization.hpp
+namespace boost { namespace serialization {
+
+template<class Archive, typename T, size_t D, typename C>
+void save(Archive & ar, boost::geometry::model::point<T, D, C> const& p, unsigned int version)
+{
+    boost::geometry::index::detail::serialize_point< boost::geometry::model::point<T, D, C> >::save(ar, p, version);
+}
+template<class Archive, typename T, size_t D, typename C>
+void load(Archive & ar, boost::geometry::model::point<T, D, C> & p, unsigned int version)
+{
+    boost::geometry::index::detail::serialize_point< boost::geometry::model::point<T, D, C> >::load(ar, p, version);
+}
+template<class Archive, typename T, size_t D, typename C>
+inline void serialize(Archive & ar, boost::geometry::model::point<T, D, C> & o, const unsigned int version) { split_free(ar, o, version); }
+
+template<class Archive, typename P>
+inline void serialize(Archive & ar, boost::geometry::model::box<P> & b, const unsigned int)
+{
+    ar & b.min_corner();
+    ar & b.max_corner();
+}
+
+}} // boost::serialization
+
+// TODO - move to index/detail/rtree/visitors/save.hpp
+namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace visitors {
+
+// TODO move saving and loading of the rtree outside the rtree, this will require adding some kind of members_view
+
+template <typename Archive, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+class save
+    : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
+{
+public:
+    typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+    typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+    typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+    save(Archive & archive, unsigned int version)
+        : m_archive(archive), m_version(version)
+    {}
+
+    inline void operator()(internal_node const& n)
+    {
+        typedef typename rtree::elements_type<internal_node>::type elements_type;
+        elements_type const& elements = rtree::elements(n);
+
+        char t = 'i';
+        size_t s = elements.size();
+        m_archive << t << s;
+
+        for (typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it)
+        {
+            serialization_save(it->first, m_archive);
+
+            rtree::apply_visitor(*this, *it->second);
+        }
+    }
+
+    inline void operator()(leaf const& l)
+    {
+        typedef typename rtree::elements_type<leaf>::type elements_type;
+        elements_type const& elements = rtree::elements(l);
+
+        char t = 'l';
+        size_t s = elements.size();
+        m_archive << t << s;
+
+        for (typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it)
+        {
+            serialization_save(*it, m_archive);
+        }
+    }
+
+private:
+    Archive & m_archive;
+    unsigned int m_version;
+};
+
+}}}}}} // boost::geometry::index::detail::rtree::visitors
+
+// TODO - move to index/detail/rtree/load.hpp
+namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree {
+
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+class load
+{
+    typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+    typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+    typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+    typedef typename Options::parameters_type parameters_type;
+
+    typedef typename Allocators::node_pointer node_pointer;
+    typedef rtree::node_auto_ptr<Value, Options, Translator, Box, Allocators> node_auto_ptr;
+    typedef typename Allocators::size_type size_type;
+
+public:
+    template <typename Archive> inline static
+    node_pointer apply(Archive & ar, unsigned int version, parameters_type const& parameters, Translator const& translator, Allocators & allocators)
+    {
+        char t;
+        ar >> t;
+
+        if ( t == 'n' )
+            return node_pointer(0);
+
+        size_t elements_count;
+        ar >> elements_count;
+
+        if ( elements_count < parameters.get_min_elements() || parameters.get_max_elements() < elements_count )
+            BOOST_THROW_EXCEPTION(std::runtime_error("rtree loading error"));
+
+        if ( t == 'i' )
+        {
+            node_pointer n = rtree::create_node<Allocators, internal_node>::apply(allocators);              // MAY THROW (A)
+            node_auto_ptr auto_remover(n, allocators);    
+            internal_node & in = rtree::get<internal_node>(*n);
+
+            typedef typename rtree::elements_type<internal_node>::type elements_type;
+            typedef typename elements_type::value_type element_type;
+            elements_type & elements = rtree::elements(in);
+
+            elements.reserve(elements_count);                                                               // MAY THROW (A)
+
+            for ( size_t i = 0 ; i < elements_count ; ++i )
+            {
+                typedef typename elements_type::value_type::first_type box_type;
+                box_type b = serialization_load<box_type>(ar);
+                node_pointer n = apply(ar, version, parameters, translator, allocators); // recursive call
+                elements.push_back(element_type(b, n));
+            }
+
+            auto_remover.release();
+            return n;
+        }
+        else if ( t == 'l' )
+        {
+            node_pointer n = rtree::create_node<Allocators, leaf>::apply(allocators);                       // MAY THROW (A)
+            node_auto_ptr auto_remover(n, allocators);
+            leaf & l = rtree::get<leaf>(*n);
+
+            typedef typename rtree::elements_type<leaf>::type elements_type;
+            typedef typename elements_type::value_type element_type;
+            elements_type & elements = rtree::elements(l);
+
+            elements.reserve(elements_count);                                                               // MAY THROW (A)
+
+            for ( size_t i = 0 ; i < elements_count ; ++i )
+            {
+                element_type el = serialization_load<element_type>(ar);                                     // MAY THROW (C)
+                elements.push_back(el);                                                                     // MAY THROW (C)
+            }
+
+            auto_remover.release();
+            return n;
+        }
+        
+        BOOST_THROW_EXCEPTION(std::runtime_error("rtree loading error"));
+        //return node_pointer(0);
+    }
+};
+
+}}}}} // boost::geometry::index::detail::rtree
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_SERIALIZATION_HPP
Modified: trunk/boost/geometry/index/rtree.hpp
==============================================================================
--- trunk/boost/geometry/index/rtree.hpp	Sat Jul 13 14:07:24 2013	(r85025)
+++ trunk/boost/geometry/index/rtree.hpp	2013-07-13 21:59:26 EDT (Sat, 13 Jul 2013)	(r85026)
@@ -62,10 +62,14 @@
 #include <boost/geometry/index/detail/rtree/utilities/view.hpp>
 
 #ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
+// query iterators
 #include <boost/geometry/index/detail/rtree/query_iterators.hpp>
 #ifdef BOOST_GEOMETRY_INDEX_DETAIL_ENABLE_TYPE_ERASED_ITERATORS
+// type-erased iterators
 #include <boost/geometry/index/detail/type_erased_iterators.hpp>
 #endif
+// serialization
+#include <boost/geometry/index/detail/serialization.hpp>
 #endif
 
 // TODO change the name to bounding_tree
@@ -166,6 +170,7 @@
 
     typedef typename allocators_type::node_pointer node_pointer;
     typedef ::boost::container::allocator_traits<Allocator> allocator_traits_type;
+    typedef detail::rtree::node_auto_ptr<value_type, options_type, translator_type, box_type, allocators_type> node_auto_ptr;
 
     friend class detail::rtree::utilities::view<rtree>;
 
@@ -1155,6 +1160,7 @@
             dst.m_members.parameters() = src.m_members.parameters();
         }
 
+        // TODO use node_auto_ptr
         if ( dst.m_members.root )
         {
             detail::rtree::visitors::destroy<value_type, options_type, translator_type, box_type, allocators_type>
@@ -1211,6 +1217,53 @@
         return distance_v.finish();
     }
 
+#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
+
+    friend class boost::serialization::access;
+
+    template<class Archive>
+    void save(Archive & ar, unsigned int version) const
+    {
+        detail::serialization_save(m_members.parameters(), ar);
+
+        ar << m_members.values_count; // might be removed
+        ar << m_members.leafs_level;  // might be removed
+        if ( m_members.root )
+        {
+            detail::rtree::visitors::save<Archive, Value, options_type, translator_type, box_type, allocators_type> save_v(ar, version);
+            detail::rtree::apply_visitor(save_v, *m_members.root);
+        }
+        else
+        {
+            char t = 'n';
+            ar << t;
+        }
+    }
+
+    template<class Archive>
+    void load(Archive & ar, unsigned int version)
+    {
+        parameters_type params = detail::serialization_load<parameters_type>(ar);
+        
+        size_type values_count, leafs_level;
+        ar >> values_count; // might be removed
+        ar >> leafs_level; // might be removed
+
+        node_pointer n = detail::rtree::load<value_type, options_type, translator_type, box_type, allocators_type>
+            ::apply(ar, version, params, m_members.translator(), m_members.allocators());                                        // MAY THROW
+
+        m_members.parameters() = params;
+        m_members.values_count = values_count;
+        m_members.leafs_level = leafs_level;
+
+        node_auto_ptr remover(m_members.root, m_members.allocators());
+        m_members.root = n;
+    }
+
+    BOOST_SERIALIZATION_SPLIT_MEMBER()
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
+
     struct members_holder
         : public translator_type
         , public Parameters