#include #include "util/EffectiveSTL.hpp" #include "SharedMap.hpp" namespace // anonymous { inline std::string toKeyType( const boost::interprocess::string & storedKey ) { return std::string( storedKey.begin(), storedKey.end() ); } inline std::string toValueType( const boost::interprocess::string & storedValue ) { return std::string( storedValue.begin(), storedValue.end() ); } inline boost::interprocess::string toStoredKeyType( const std::string & key ) { return boost::interprocess::string( key.begin(), key.end() ); } inline boost::interprocess::string toStoredValueType( const std::string & value ) { return boost::interprocess::string( value.begin(), value.end() ); } } // end namespace [anonymous] namespace Tony { #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 )::setOneValue( const KeyType & key, const ValueType & value ) { ShmScopedLock lock( *m_pMutex ); efficientAddOrUpdateUnordered( *m_pMap, toStoredKeyType( key ), toStoredValueType( value ) ); } SHARED_MAP( bool )::getOneValue( const KeyType & key, ValueType & value ) { ShmScopedLock lock( *m_pMutex ); typename ShmMapType::iterator f = m_pMap->find( toStoredKeyType( key ) ); if ( f != m_pMap->end() ) { value = toValueType( f->second ); return true; } else { return false; } } SHARED_MAP( void )::setManyValues( const KeyVector & keys, const ValueVector & values ) { if ( keys.size() != values.size() ) throw std::invalid_argument( "setManyValues: # keys != # values" ); ShmScopedLock lock( *m_pMutex ); for ( std::size_t i = 0; i < keys.size(); ++i ) { efficientAddOrUpdateUnordered( *m_pMap, toStoredKeyType( keys[i] ), toStoredValueType( values[i] ) ); } } SHARED_MAP( void )::setManyValues( typename KeyVector::const_iterator & keysBegin, typename KeyVector::const_iterator & keysEnd, typename ValueVector::const_iterator & valuesBegin ) { ShmScopedLock lock( *m_pMutex ); typename KeyVector::const_iterator keys = keysBegin; typename ValueVector::const_iterator values = valuesBegin; while ( keys != keysEnd ) { efficientAddOrUpdateUnordered( *m_pMap, toStoredKeyType( *keys ), toStoredValueType( *values ) ); ++keys; ++values; } } SHARED_MAP( void )::getManyValues( const KeyVector & keys, ValueVector & values ) { if ( keys.size() != values.size() ) throw std::invalid_argument( "getManyValues: # keys != # values" ); ShmScopedLock lock( *m_pMutex ); for ( std::size_t i = 0; i < keys.size(); ++i ) { typename ShmMapType::iterator f = m_pMap->find( toStoredKeyType( keys[i] ) ); if ( f != m_pMap->end() ) values[i] = toValueType( f->second ); } } SHARED_MAP( void )::getManyValues( typename KeyVector::const_iterator & keysBegin, typename KeyVector::const_iterator & keysEnd, typename ValueVector::iterator & valuesBegin ) { ShmScopedLock lock( *m_pMutex ); typename KeyVector::const_iterator keys = keysBegin; typename ValueVector::iterator values = valuesBegin; while ( keys != keysEnd ) { typename ShmMapType::iterator f = m_pMap->find( toStoredKeyType( *keys ) ); if ( f != m_pMap->end() ) *values = toValueType( f->second ); ++keys; ++values; } } SHARED_MAP( bool )::deleteOneKey( const KeyType & key ) { ShmScopedLock lock( *m_pMutex ); return ( m_pMap->erase( toStoredKeyType( key ) ) > 0 ); } SHARED_MAP( std::size_t )::deleteManyKeys( const std::vector< KeyType > & keys ) { ShmScopedLock lock( *m_pMutex ); std::size_t nErased = 0; for ( std::size_t i = 0; i < keys.size(); ++i ) { if ( m_pMap->erase( toStoredKeyType( keys[i] ) ) > 0 ) ++nErased; } return nErased; } SHARED_MAP( void )::clear() { ShmScopedLock lock( *m_pMutex ); m_pMap->clear(); } SHARED_MAP( /* static */ void )::removeMapping( const std::string & shmName ) { boost::interprocess::shared_memory_object::remove( shmName.c_str() ); } SHARED_MAP( std::ostream & )::ShmStats::dumpTo( std::ostream & os ) { os << ( boost::format( " %d free (%.1f%%) of %d total; %d named, %d unique" ) % nFreeBytes % ( 100.0 * nFreeBytes / nTotalBytes ) % nTotalBytes % nNamedObjs % nUniqueObjs ); } SHARED_MAP( void )::getShmStats( struct ShmStats & stats ) { stats.nTotalBytes = m_manager.get_size(); stats.nFreeBytes = m_manager.get_free_memory(); stats.nNamedObjs = m_manager.get_num_named_objects(); stats.nUniqueObjs = m_manager.get_num_unique_objects(); } // --------------------------------------------------------------------- // instantiations template class SharedMap< /* KeyType = */ std::string, /* ValueType = */ std::string, /* StoredKeyType = */ boost::interprocess::string, /* StoredValueType = */ boost::interprocess::string >; } // end namespace Tony