|
Boost Users : |
Subject: [Boost-users] [interprocess] shared map of string to string?
From: Anthony Foiani (tkil_at_[hidden])
Date: 2010-01-19 21:50:40
I'm using boost.interprocess to build a map from string to string that
can be shared between multiple processes, with all read/write access
protected by a mutex. I'm having a hard time making it work.
Here's a cut-down version of the declaration:
template < typename KeyType,
typename ValueType,
typename StoredKeyType = KeyType,
typename StoredValueType = ValueType >
class SharedMap
: private boost::noncopyable
{
public:
SharedMap( const std::string & shmName,
const std::size_t shmSize,
const std::size_t initBucketCount = 10 );
~SharedMap();
void setOneValue( const KeyType & key,
const ValueType & value );
bool getOneValue( const KeyType & key,
ValueType & value );
void clear();
private:
typedef std::pair<
const StoredKeyType,
StoredValueType
> StoredPairType;
typedef boost::interprocess::managed_shared_memory ShmManagerType;
typedef boost::interprocess::allocator<
StoredPairType,
ShmManagerType::segment_manager
> ShmAllocatorType;
typedef boost::interprocess::interprocess_mutex ShmMutexType;
typedef boost::interprocess::scoped_lock< ShmMutexType > ShmScopedLock;
typedef boost::unordered_map<
StoredKeyType,
StoredValueType,
boost::hash< StoredKeyType >,
std::equal_to< StoredKeyType >,
ShmAllocatorType
> ShmMapType;
std::string m_sShmName;
ShmManagerType m_manager;
ShmMutexType * m_pMutex;
ShmMapType * m_pMap;
}; // end class SharedMap
typedef SharedMap<
/* KeyType = */ std::string,
/* ValueType = */ std::string,
/* StoredKeyType = */ boost::interprocess::string,
/* StoredValueType = */ boost::interprocess::string
> SharedStringMap;
And some important bits of the implementation:
#define SHARED_MAP( ret_type ) \
template < \
typename KeyType, \
typename ValueType, \
typename StoredKeyType, \
typename StoredValueType \
> \
ret_type \
SharedMap< \
KeyType, \
ValueType, \
StoredKeyType, \
StoredValueType \
>
SHARED_MAP()::SharedMap(
const std::string & shmName,
const std::size_t shmSize,
const std::size_t initBucketCount /* = 10 */
)
: m_sShmName( shmName ),
m_manager( boost::interprocess::open_or_create,
shmName.c_str(), shmSize ),
m_pMutex( m_manager.find_or_construct< ShmMutexType >( "mutex" )() ),
m_pMap( m_manager.find_or_construct< ShmMapType >( "map" )(
initBucketCount,
boost::hash< StoredKeyType >(),
std::equal_to< StoredKeyType >(),
m_manager.get_allocator< StoredPairType >()
) )
{
}
SHARED_MAP()::~SharedMap()
{
try
{
m_pMutex->unlock();
}
catch ( ... )
{
}
}
SHARED_MAP( void )::clear()
{
ShmScopedLock lock( *m_pMutex );
m_pMap->clear();
}
It works fine the first time I run the program, but on the second
attempt I get a SIGSEGV when I try to clear the map. My test loop is
basically:
create or find map
for each rep
clear map
insert values
done
GDB tells me that this error is originating here:
Program received signal SIGSEGV, Segmentation fault.
__libc_free (mem=0x8143a48) at malloc.c:3709
3709 if (chunk_is_mmapped(p)) /* release mmapped memory. */
(gdb) bt
#0 __libc_free (mem=0x8143a48) at malloc.c:3709
#1 0x001efd12 in operator delete (ptr=<value optimized out>)
at ../../../../libstdc++-v3/libsupc++/del_op.cc:44
#2 0x08053d49 in __gnu_cxx::new_allocator<char>::deallocate (this=0xb7fa4334,
__p=0x8143a48 <Address 0x8143a48 out of bounds>)
at /usr/lib/gcc/i686-redhat-linux/4.4.2/../../../../include/c++/4.4.2/ext/new_allocator.h:95
#3 0x0805e677 in boost::interprocess_container::containers_detail::basic_string_base<std::allocator<char> >::deallocate (this=0xb7fa4334, p=0x8143a48 <Address 0x8143a48 out of bounds>, n=24)
at /usr/include/boost/interprocess/containers/container/string.hpp:309
#4 0x0805dac2 in boost::interprocess_container::containers_detail::basic_string_base<std::allocator<char> >::deallocate_block (this=0xb7fa4334)
at /usr/include/boost/interprocess/containers/container/string.hpp:341
#5 0x0805d167 in boost::interprocess_container::containers_detail::basic_string_base<std::allocator<char> >::~basic_string_base (this=0xb7fa4334, __in_chrg=<value optimized out>)
at /usr/include/boost/interprocess/containers/container/string.hpp:119
#6 0x0805bfe7 in {b::ic::string}::~basic_string (this=0xb7fa4334, __in_chrg=<value optimized out>)
at /usr/include/boost/interprocess/containers/container/string.hpp:617
#7 0x0805d671 in std::pair<{b::ic::string} const, {b::ic::string} >::~pair (this=0xb7fa4334, __in_chrg=<value optimized out>)
at /usr/lib/gcc/i686-redhat-linux/4.4.2/../../../../include/c++/4.4.2/bits/stl_pair.h:68
#8 0x08063636 in boost::unordered_detail::destroy<std::pair<{b::ic::string} const, {b::ic::string} > > (x=0xb7fa4334)
at /usr/include/boost/unordered/detail/hash_table.hpp:233
#9 0x08062d55 in boost::unordered_detail::hash_table_data_unique_keys<ip::allocator<std::pair<{b::ic::string} const, {b::ic::string} >, ip::segment_manager<char, ip::rbtree_best_fit<ip::mutex_family, ip::offset_ptr<void>, 0u>, ip::iset_index> > >::allocators::destroy (this=0xb7f9f0d4, ptr=...) at /usr/include/boost/unordered/detail/hash_table_impl.hpp:133
#10 0x080619fc in boost::unordered_detail::hash_table_data_unique_keys<ip::allocator<std::pair<{b::ic::string} const, {b::ic::string} >, ip::segment_manager<char, ip::rbtree_best_fit<ip::mutex_family, ip::offset_ptr<void>, 0u>, ip::iset_index> > >::delete_to_bucket_end (this=0xb7f9f0d4, begin=...) at /usr/include/boost/unordered/detail/hash_table_impl.hpp:832
#11 0x0805fc63 in boost::unordered_detail::hash_table_data_unique_keys<ip::allocator<std::pair<{b::ic::string} const, {b::ic::string} >, ip::segment_manager<char, ip::rbtree_best_fit<ip::mutex_family, ip::offset_ptr<void>, 0u>, ip::iset_index> > >::clear_bucket (
this=0xb7f9f0d4, b=...) at /usr/include/boost/unordered/detail/hash_table_impl.hpp:867
#12 0x0805e2ff in boost::unordered_detail::hash_table_data_unique_keys<ip::allocator<std::pair<{b::ic::string} const, {b::ic::string} >, ip::segment_manager<char, ip::rbtree_best_fit<ip::mutex_family, ip::offset_ptr<void>, 0u>, ip::iset_index> > >::clear (
this=0xb7f9f0d4) at /usr/include/boost/unordered/detail/hash_table_impl.hpp:879
#13 0x0805d918 in boost::unordered_map<{b::ic::string}, {b::ic::string}, boost::hash<{b::ic::string} >, std::equal_to<{b::ic::string} >, ip::allocator<std::pair<{b::ic::string} const, {b::ic::string} >, ip::segment_manager<char, ip::rbtree_best_fit<ip::mutex_family, ip::offset_ptr<void>, 0u>, ip::iset_index> > >::clear (this=0xb7f9f0c4)
at /usr/include/boost/unordered/unordered_map.hpp:271
#14 0x0805cdc3 in Tony::SharedMap<{std::string}, {std::string}, {b::ic::string}, {b::ic::string} >::clear (this=0xbffff40c) at SharedMap.cpp:203
#15 0x0804e3e4 in main (argc=1, argv=0xbffff744) at SharedMapTest.cpp:99
I've done the following substitutions:
std::basic_string<char, std::char_traits<char>, std::allocator<char> >
-> {std::string}
boost::interprocess_container::basic_string<char,
std::char_traits<char>,
std::allocator<char> >
-> {b::ic::string}
ip::
-> ip::
Interestingly, it looks like the mutex survives program stops and
starts just fine: if I try to run my test case a third time, it sits
and waits on the mutex (which got locked just before the 'clear'
crashed out in the 2nd invocation)
Platform is GCC 4.4.2 (fedora rpm 4.4.2-20) with the RPM packages of
boost (1.39.0-8).
Any hints would be very much appreciated.
I can get a full working test case up on the web, but I need to pull
out some bits (especially from the test routine) that rely on other
parts of my project.
Alternately, if anyone knows of a freely-available implementation of
this functionality (or, even better, one that stores std::strings
directly instead of having to go to/from b::ip::strings, and maybe one
that auto-sizes its shared memory pool)... I'd *definitely* like to
hear about that. :)
Thanks in advance!
Regards,
Tony
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net