我有一个stl map
容器,我需要在初始化后只读(读取:线程安全),以防止我的某个程序的线程可能出现试图改变它,从而导致竞争条件。此地图使用std::make_pair
。
目前,我有三个地图,都被声明为类mmapper
的静态成员,以相同的方式实现,只是具有不同的值:
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"));
}
}
这些由一个访问函数解析:
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";
}
}
所以我的问题是,如何防止我的线程修改此线程?我在考虑让地图只是static const
,但我不确定如何使用std::pair
实现这些地图。
我通常不会在乎,但这会在约20分钟后不断抛出段错误。 :(
这是回溯:
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()() ()
答案 0 :(得分:1)
如果在初始化后再也没有再次更改mmapper,我只能在mmapper::getKeyFromMap()
看到两个故障点:
参数。所有这些都是对外部数据的引用。如果删除外部数据,则可能发生随机异常。将它们从const int&
更改为int
。 “按值传递”是原始类型(check this post)的最佳方法。
记录器。你确定它的实现是线程安全的吗?它的内部数据正在频繁变化,因此它是一个很好的失败点。
异常似乎来自basic_string.tcc第174行,由mmapper第65行调用。这些行可能会为您提供更好的问题线索。