C++ 字符串共享内存映射向量
如何将字符串附加到地图中包含的向量?结构是map(float,vector(string)),其中map位于共享内存中。我的问题是,如果key==所需的key,那么将string附加到字符串的向量中 你的意思是这样的:C++ 字符串共享内存映射向量,c++,boost,shared-memory,C++,Boost,Shared Memory,如何将字符串附加到地图中包含的向量?结构是map(float,vector(string)),其中map位于共享内存中。我的问题是,如果key==所需的key,那么将string附加到字符串的向量中 你的意思是这样的: #include <map> #include <vector> #include <string> #include <iostream> int main() { std::map<float, std:
#include <map>
#include <vector>
#include <string>
#include <iostream>
int main()
{
std::map<float, std::vector<std::string>> m;
m[.5f].emplace_back("First");
m[.5f].emplace_back("Second");
m[.0f].emplace_back("Hello");
m[.0f].emplace_back("World");
for(const auto& [key, value] : m)
{
std::cout << "Key: " << key << '\n';
for(const auto& str : value)
std::cout << '\t' << str << '\n';
}
std::cout.flush();
return 0;
}
#包括
#包括
#包括
#包括
int main()
{
std::map m;
m[.5f]。向后放置(“第一”);
m[.5f]。向后放置(“第二”);
m[.0f]。向后放置(“你好”);
m[.0f]。向后放置(“世界”);
用于(常数自动和[键,值]:m)
{
实际上,在共享内存中执行此操作非常困难
如果所有的分配器都正确,并且添加了锁,通常会得到非常笨拙的代码,因为所有分配器都在传递,所以很难读取
然而,您可以使用Boost的作用域分配器适配器,它将发挥很多(很多)魔力,让生活变得更好
我认为下面的代码示例正好是最合适的
警告:这是建立在多年的经验基础上的。如果您刚好不在“魔法”的范围之内(主要是由于使用\u分配器
和作用域\u分配器\u适配器
)你会发现它崩溃了,你会编写很多手动构造函数/转换调用来让它工作
#define DEMO
#include <iostream>
#include <iomanip>
#include <mutex>
#include <boost/interprocess/containers/map.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/managed_mapped_file.hpp> // For Coliru (doesn't support shared memory)
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/container/scoped_allocator.hpp>
namespace bip = boost::interprocess;
namespace bc = boost::container;
namespace Shared {
using Segment = bip::managed_mapped_file; // Coliru doesn't support bip::managed_shared_memory
template <typename T> using Alloc = bc::scoped_allocator_adaptor<bip::allocator<T, Segment::segment_manager> >;
template <typename V>
using Vector = bip::vector<V, Alloc<V> >;
template <typename K, typename V, typename Cmp = std::less<K> >
using Map = bip::map<K, V, Cmp, Alloc<std::pair<K const, V> > >;
using String = bip::basic_string<char, std::char_traits<char>, Alloc<char> >;
using Mutex = bip::interprocess_mutex;
}
namespace Lib {
using namespace Shared;
struct Data {
using Map = Shared::Map<float, Shared::Vector<Shared::String> >;
mutable Mutex _mx;
Map _map;
template <typename Alloc> Data(Alloc alloc = {}) : _map(alloc) {}
bool append(float f, std::string s) {
std::lock_guard<Mutex> lk(_mx); // lock
auto it = _map.find(f);
bool const exists = it != _map.end();
#ifndef DEMO
if (exists) {
it->second.emplace_back(s);
}
#else
// you didn't specify this, but lets insert new keys here, if
// only for the demo
_map[f].emplace_back(s);
#endif
return exists;
}
size_t size() const {
std::lock_guard<Mutex> lk(_mx); // lock
return _map.size();
}
friend std::ostream& operator<<(std::ostream& os, Data const& data) {
std::lock_guard<Mutex> lk(data._mx); // lock
for (auto& [f,v] : data._map) {
os << f << " ->";
for (auto& ss : v) {
os << " " << std::quoted(std::string(ss));
}
os << "\n";
}
return os;
}
};
}
struct Program {
Shared::Segment msm { bip::open_or_create, "data.bin", 10*1024 };
Lib::Data& _data = *msm.find_or_construct<Lib::Data>("data")(msm.get_segment_manager());
void report() const {
std::cout << "Map contains " << _data.size() << " entries\n" << _data;
}
};
struct Client : Program {
void run(float f) {
_data.append(f, "one");
_data.append(f, "two");
}
};
int main() {
{
Program server;
server.report();
Client().run(.5f);
Client().run(.6f);
}
// report again
Program().report();
}
第二次运行:
Map contains 2 entries
0.5 -> "one" "two"
0.6 -> "one" "two"
Map contains 2 entries
0.5 -> "one" "two" "one" "two"
0.6 -> "one" "two" "one" "two"
请花一些时间重新阅读,尤其是和。还有和。最后,不要忘记如何创建。映射是否在共享内存中并不重要,至少不是访问本身。但可能需要一个信号量或互斥来防止多个并行访问。使用浮点数进行相等比较几乎总是一个坏主意。@Rene为什么这不重要?我同意,在没有代码的情况下,我们只能从概念上讲。从概念上讲,这并不重要。但从技术上讲,它在很多细节上都很重要。人们往往忘记,虽然分配器是一个很好的抽象,但共享内存分配器必然是有状态的,而有状态分配器需要大量的li程序员提供的brary支持和支持。我已在一个进程中使用托管共享内存初始化和分配映射对象。我需要在另一个进程中向其中添加更多元素。需要扩展映射或向量。@Max这是非常简单的。如果没有高级机制,这些都不能转换为共享内存容器(作用域分配器),即使这样,它也绕过了构造参数转发机制的边缘。我将发布一个答案,只是为了说明……如果您面临挑战,您可以尝试以自然方式编写不存在的分支(比如\u map.emplace(f,{s});
,就像您通常能够编写的那样)当然,我的解决方案通过使用默认的操作符[]
来欺骗这一点。
Map contains 2 entries
0.5 -> "one" "two"
0.6 -> "one" "two"
Map contains 2 entries
0.5 -> "one" "two" "one" "two"
0.6 -> "one" "two" "one" "two"