|
Geometry : |
Subject: [geometry] Crash in rtree after growing shared memory, VS2012 x64, Boost 1.55
From: Tim Finer (tim.finer_at_[hidden])
Date: 2014-07-25 13:49:02
Hello,
I really want to use a persistent rtree backed by shared memory (or a
memory mapped file). I don't know in advance how large the data. I
experimented with resizing a boost::vector backed by a shared memory
allocator and applied what I found there to the example at
http://www.boost.org/doc/libs/1_55_0/libs/geometry/doc/html/geometry/spatial_indexes/rtree_examples/index_stored_in_shared_memory_using_boost_interprocess.html.
What I did was wrap an insertion function that catches a bad_alloc,
closes the shared memory segment, grows the shared memory, then resets
the pointer to the rtree. I've verified that this technique works fine
for boost::vector, but not for the rtree, because it appears that there
are some other structures internally that are possibly noting the (old)
capacity of the shared memory?
I also noted in a previous thread a similar problem, and applied the fix
on github, but that didn't help
(http://boost-geometry.203548.n3.nabble.com/rtree-crash-when-used-with-inter-process-td4026037.html).
namespace bg = boost::geometry;
namespace bgm = boost::geometry::model;
namespace bgi = boost::geometry::index;
namespace bi = boost::interprocess;
typedef bgm::point<double, 3, bg::cs::cartesian> bgPoint3;
typedef std::pair<bgPoint3, std::uint64_t> bgValue;
typedef bgm::box<bgPoint3> bgBox3;
typedef bgi::linear<16> Partitioner;
typedef bgi::indexable<bgValue> Indexer;
typedef bgi::equal_to<bgValue> Comparator;
typedef bi::allocator<bgValue,
bi::managed_shared_memory::segment_manager> Allocator;
typedef bgi::rtree<bgValue, Partitioner, Indexer, Comparator,
Allocator > bgMemRTree;
typedef std::unique_ptr<bi::managed_shared_memory> MemPtr;
inline void ResizingInsert(MemPtr& mem, bgMemRTree*& rtree, const
bgPoint3& pt, std::uint64_t i)
{
try
{
rtree->insert(std::make_pair(pt, i));
}
catch(bi::bad_alloc&)
{
auto newSize = static_cast<size_t>(mem->get_size() * 0.5);
// Close
mem.reset();
bi::managed_shared_memory::grow("RTree-Test", newSize);
mem.reset(new bi::managed_shared_memory(bi::open_only,
"RTree-Test"));
rtree = mem->find<bgMemRTree>("rtree").first;
// Try again, let bad_alloc out if this fails a second time.
rtree->insert(std::make_pair(pt, i));
}
}
MemPtr mem(new bi::managed_shared_memory(bi::create_only,
"RTree-Test", 1024 * 64));
for ( std::uint64_t i = 0 ; i < 50000; ++i )
ResizingInsert( mem, rtree, bgPoint3(rndDbl(prng), rndDbl(prng),
rndDbl(prng)), i);
Dies down in
Boost_1.55.0\Boost\boost\geometry\index\detail\varray.hpp:74
BOOST_GEOMETRY_INDEX_ASSERT(s <= v.capacity(), "size too big");
I'm not married to the way I'm doing this, and welcome any suggestions
or workarounds. My other thought is copying the entire tree into a new
(larger) shared memory segment, but I'm sure that'll be a huge
performance hit.
Thanks in Advance,
Tim
Geometry list run by mateusz at loskot.net