I've got an stl map
container that I need to be read-only (read: thread-safe) after initialization, to prevent the possibility of one of my program's threads from trying to make a change to it, and thus causing a race condition. this map uses std::make_pair
.
At present, I have three maps, all declared as static members of class mmapper
, implemented the same way, just with different values:
class mmapper {
public:
mmapper();
std::string getKeyFromMap( const int &key1, const int &key2, const int &mid );
static std::map<RgCodeUidPair, std::string> siteMap;
static std::map<TPCodeUidPair, std::string> cachedData;
static std::map<DLpair, std::string> Ddlabel;
private:
void createTypeMap();
void createSiteMap();
void createDriveLetterMap();
};
typedef std::pair<int, int> TPCodeUidPair;
typedef std::pair<int, int> RgCodeUidPair;
typedef std::pair<int, int> DLpair;
void mmapper::createSiteMap() {
logger _logger( glob.g_ll, glob.g_logfile );
_logger.logstream << "Loading Site Map.";
_logger.log( 0 );
if ( siteMap.empty() ) {
siteMap.insert(std::make_pair(std::make_pair(0, 0), "AUS"));
siteMap.insert(std::make_pair(std::make_pair(0, 1), "AUS2"));
siteMap.insert(std::make_pair(std::make_pair(1, 0), "DCA"));
siteMap.insert(std::make_pair(std::make_pair(1, 1), "DCA1"));
siteMap.insert(std::make_pair(std::make_pair(1, 2), "DCA2"));
siteMap.insert(std::make_pair(std::make_pair(1, 3), "DCA3"));
siteMap.insert(std::make_pair(std::make_pair(1, 4), "DCAg"));
siteMap.insert(std::make_pair(std::make_pair(1, 4), "LAX"));
siteMap.insert(std::make_pair(std::make_pair(1, 5), "MIA"));
siteMap.insert(std::make_pair(std::make_pair(1, 6), "TOR"));
siteMap.insert(std::make_pair(std::make_pair(1, 7), "NYC"));
siteMap.insert(std::make_pair(std::make_pair(2, 0), "AMS"));
siteMap.insert(std::make_pair(std::make_pair(2, 1), "AMS1"));
siteMap.insert(std::make_pair(std::make_pair(2, 2), "AMS2"));
siteMap.insert(std::make_pair(std::make_pair(2, 3), "AMS3"));
siteMap.insert(std::make_pair(std::make_pair(2, 4), "LON"));
siteMap.insert(std::make_pair(std::make_pair(2, 5), "ZUR"));
siteMap.insert(std::make_pair(std::make_pair(2, 6), "WAR"));
siteMap.insert(std::make_pair(std::make_pair(3, 0), "HKG"));
siteMap.insert(std::make_pair(std::make_pair(3, 1), "SGP"));
siteMap.insert(std::make_pair(std::make_pair(3, 2), "TOK"));
siteMap.insert(std::make_pair(std::make_pair(3, 3), "SYD"));
}
}
These are parsed by a single accessor function:
std::string mmapper::getKeyFromMap( const int &key1, const int &key2, const int &mid ) {
logger _logger( glob.g_ll, glob.g_logfile );
switch( mid ) {
case 1: {
_logger.logstream << "Retrieving key values for Server Type.";
_logger.log( 1 );
auto it = cachedData.find(std::make_pair(key1, key2));
if( it != cachedData.end() ) {
_logger.logstream << "Successfully retrieved key value";
_logger.log( 1 );
return it->second;
}
else {
_logger.logstream << "Failed to retrieve key.";
_logger.log( 3 );
return "ERR";
}
break;
}
case 2: {
_logger.logstream << "Retrieving key values for Server Site.";
_logger.log( 1 );
auto it = siteMap.find(std::make_pair(key1, key2));
if( it != siteMap.end() ) {
_logger.logstream << "Successfully retrieved key value";
_logger.log( 1 );
return it->second;
}
else {
_logger.logstream << "Failed to retrieve key.";
_logger.log( 3 );
return "ERR";
}
break;
}
case 3: {
_logger.logstream << "Retrieveing key values for drive label";
_logger.log( 1 );
auto it = Ddlabel.find( std::make_pair( key1, key2 ));
if( it != Ddlabel.end() ) {
_logger.logstream << "Successfully retrieved key value";
_logger.log( 1 );
return it->second;
}
else {
_logger.logstream << "Failed to retrieve key.";
_logger.log( 3 );
return "ERR";
}
break;
}
default:
_logger.logstream << "Invalid value passed to mapper! Err 3";
_logger.log( 5 );
return "ERR";
}
}
So my question here is, how can I prevent my threads from modifying this thread? I was thinking of having the maps simply be static const
but I'm unsure how to implement that with std::pair
.
I normally wouldn't care, but this keeps throwing segfaults after ~20 minutes. :(
Here is backtrace:
at /usr/src/debug/gcc-4.4.7-20120601/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/bits/basic_string.tcc:174
#1 0x000000000040f47c in mmapper::getKeyFromMap (this=0x7fff42554ccf, key1=@0x7fffac012f60, key2=@0x7fffac012f64,
mid=@0x7fff42554cec) at include/mmapper.cpp:65
#2 0x0000000000436bee in ddrive::readDriveData (this=0x7fff425550b0, data1=
std::vector of length 576, capacity 1024 = {...}, db=...) at include/drive.cpp:83
#3 0x00000000004162f2 in handle_data(std::vector<int, std::allocator<int> >&) ()
#4 0x0000000000416fd7 in session(boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >) ()
#5 0x00000000004249ac in void boost::_bi::list1<boost::_bi::value<boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > > > >::operator()<void (*)(boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >), boost::_bi::list0>(boost::_bi::type<void>, void (*&)(boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >), boost::_bi::list0&, int) ()
#6 0x00000000004247bf in boost::_bi::bind_t<void, void (*)(boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >), boost::_bi::list1<boost::_bi::value<boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > > > > >::operator()() ()