Dan*_*ere 2 c++ boost shared-memory visual-studio
我正在使用 C++ 中 boost 库的共享内存,我试图分配一个 unordered_map 与其他进程共享。服务器端代码如下:
地图创建器.h
//#pragma once
#pragma warning( disable :4494 )
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/managed_mapped_file.hpp>
#include <boost/functional/hash.hpp>
#include <boost/unordered_map.hpp>
#include <iostream>
struct dataClass {
double Somma;
int Contatore;
};
namespace bip = boost::interprocess;
namespace bc = boost::container;
#ifdef COLIRU
using Segment = bip::managed_mapped_file;
#else
using Segment = bip::managed_shared_memory;
#endif
using Mgr = Segment::segment_manager;
template <typename T> using Alloc = bip::allocator<T, Mgr>;
using MyString = bc::basic_string<char, std::char_traits<char>, Alloc<char>>;
using KeyType = MyString;
using MappedType = dataClass;
using ValueType = std::pair<KeyType const, MappedType>;
using MySHMMap = boost::unordered_map<KeyType, MappedType, boost::hash<MyString>,
std::equal_to<MyString>, Alloc<ValueType>>;
class MapCreator {
public:
static constexpr int sizeDeclared = 1324*1024*1024; //< Here the problem, if i set 2000*1024*1024, the client application throw error
MapCreator(const char* Nome) // : nameMemory(Nome)
{
nameMemory = Nome;
remove();
segment = Segment{ bip::create_only, nameMemory, sizeDeclared };
mappa = segment.find_or_construct<MySHMMap>("MySHMMapName")(segment.get_segment_manager());
}
dataClass getValue(std::string key) const {
return mappa->at(MyString(key.c_str(), segment.get_segment_manager()));
}
void insertValue(std::string key,dataClass value) {
mappa->emplace(MyString(key.c_str(), segment.get_segment_manager()),
value);
}
double getFreeMemory() {
return ((double)segment.get_free_memory() / 1024 / 1024 / 1024);
}
long getSize() {
return mappa->size();
}
void remove() {
bip::shared_memory_object::remove(nameMemory);
}
double getTotalSize() {
return (double)sizeDeclared/1024/1024/1024;
}
double getTotalMemory() {
return (double)segment.get_size() / 1024 / 1024 / 1024;
}
private:
// note: declaration order defines initialization order!
const char* nameMemory = "SharedMemoryName";
Segment segment;//{ bip::open_or_create, nameMemory, sizeDeclared };
MySHMMap* mappa = nullptr;
};
Run Code Online (Sandbox Code Playgroud)
同时主要代码是这样的:
#include "MapCreator.h"
int main(){
MapCreator mappaClass("thread1");
mappaClass.insertValue("a", dataClass{ 3.12,2123 });
}
Run Code Online (Sandbox Code Playgroud)
Reader的代码如下:
ReaderFromMemory.h
//#pragma once
#pragma warning( disable :4494 )
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/managed_mapped_file.hpp>
#include <boost/functional/hash.hpp>
#include <boost/unordered_map.hpp>
#include <iostream>
struct dataClass {
double Somma;
int Contatore;
};
namespace bip = boost::interprocess;
namespace bc = boost::container;
#ifdef COLIRU
using Segment = bip::managed_mapped_file;
#else
using Segment = bip::managed_shared_memory;
#endif
using Mgr = Segment::segment_manager;
template <typename T> using Alloc = bip::allocator<T, Mgr>;
using MyString = bc::basic_string<char, std::char_traits<char>, Alloc<char>>;
using KeyType = MyString;
using MappedType = dataClass;
using ValueType = std::pair<KeyType const, MappedType>;
using MySHMMap = boost::unordered_map<KeyType, MappedType, boost::hash<MyString>,
std::equal_to<MyString>, Alloc<ValueType>>;
class Reader {
public:
Reader() : mappa(segment.find_or_construct<MySHMMap>("MySHMMapName")(
segment.get_segment_manager()))
{
}
dataClass getValue(const char* key) const {
return mappa->at(MyString(key, segment.get_segment_manager())); // < Here is the error while reading
}
private:
// note: declaration order defines initialization order!
static constexpr char const* nameMemory = "thread1";
Segment segment{ bip::open_only, nameMemory };;
MySHMMap* mappa = nullptr;
};
Run Code Online (Sandbox Code Playgroud)
这是主要的:
#include "ReaderFromMemory.h"
int main(){
Reader reader;
auto testValue = reader.getValue("a");
}
Run Code Online (Sandbox Code Playgroud)
所以问题是分配和读取超过2GB。
我已经尝试使用 /LARGEADDRESSAWARE 标志,但对于我正在使用的 Reader 不起作用:
Visual Studio 2022 用于在 x86 模式下编译,因为读取器是 VB6 使用的 DLL
升压库版本1.78.0
由于这应该在 32 位环境中工作,因此您可以在直接访问您现在拥有的一张地图的顶部放置一个图层。以下是该想法的概述:
uint64_t hasher64(const KeyType& kt) {
//...
}
namespace std {
struct hash<KeyType> {
size_t operator()(const KeyType& kt) const {
return hasher64(kt) & 0xFFFFFFFF;
}
};
}
MySHMMap& getmap(const KeyType& kt) {
static MySHMMap maps[16];
return maps[(hasher64(kt) >> 32) & 0xF];
}
// ...
getmap(my_key)[my_key] = "foo";
Run Code Online (Sandbox Code Playgroud)
上面的代码对密钥进行了两次哈希处理,但会为您面临的限制提供解决方法。
您还可以有一个单独的、更便宜的功能来选择较小的地图。如果您的键是 a std::string,则可以通过查看字符串中的第一个字符来进行选择。
using KeyType = std::string;
MySHMMap& getmap(const KeyType& kt) {
static MySHMMap maps[16];
if(kt.empty()) return maps[0];
return maps[kt[0] & 0xF];
}
Run Code Online (Sandbox Code Playgroud)
实现可以这样开始(但绝不是完整的)。我使用了标准类型和容器,以免与boost细节混淆,但这个想法应该可行。
using KeyType = std::string;
MySHMMap& getmap(const KeyType& kt) {
static MySHMMap maps[16];
if(kt.empty()) return maps[0];
return maps[kt[0] & 0xF];
}
Run Code Online (Sandbox Code Playgroud)
上面的默认设置MapOverlay是使用MapSelector std::hash<KeyType>每个键上的 来选择地图。这可能比您需要的要贵得多,因此您可以更快地提供一些东西作为替代方案。如果您使用不同的实现来构建它,那么使用std::hash<KeyType>也有点风险。MapSelector共享地图的所有程序中的算法必须相同。
#include <unordered_map>
#include <iostream>
template<class KeyType, class MappedType, size_t MapCo,
class MapSelector = std::hash<KeyType>>
class MapOverlay {
public:
using MySHMMap = std::unordered_map<KeyType, MappedType>;
using value_type = typename MySHMMap::value_type;
struct iterator { // an iterator to iterate seamlessly over the multiple maps
iterator(MapOverlay* mo, MySHMMap& m, typename MySHMMap::iterator c) :
mo(mo), map(&m), it(c)
{
find_non_empty(); // find the first map with values
}
value_type& operator*() { return *it; }
value_type* operator->() { return &*it; }
iterator& operator++() {
if(it == map->end()) {
++map;
it = map->begin();
} else ++it;
find_non_empty();
return *this;
}
bool operator==(const iterator& rhs) const {
return map == rhs.map && it == rhs.it;
}
bool operator!=(const iterator& rhs) const { return !(*this == rhs); }
private:
void find_non_empty() { // find the next map with values
while(it == map->end() && map != &mo->maps[MapCo-1]) {
++map;
it = map->begin();
}
}
MapOverlay* mo;
MySHMMap* map;
typename MySHMMap::iterator it;
}; // iterator end
// some member functions making it feel like a normal unordered_map
MappedType& operator[](const KeyType& kt) {
return map_lookup(kt)[kt];
}
iterator find(const KeyType& kt) {
auto& m = map_lookup(kt);
auto it = m.find(kt);
if(it == m.end()) return end();
return {this, m, it};
}
iterator begin() { return {this, maps[0], maps[0].begin()}; }
iterator end() { return {this, maps[MapCo-1], maps[MapCo-1].end()}; }
private:
MySHMMap& map_lookup(const KeyType& kt) {
// call the map selector for `kt` and use `% MapCo` to get it in range
return maps[ms(kt) % MapCo]; // ms is an instance of MapSelector
}
MySHMMap maps[MapCo];
MapSelector ms;
};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
180 次 |
| 最近记录: |