c++ - 如何搜索存储在 Boost::managed_shared_memory 段中的 Boost::interprocess::map 作为 open_read_only?
问题描述
我有一个 Boost:interprocess::unordered_map,它有一个字符串类型的键和一个字符串类型的值。该映射存储在 managed_shared_memory 段中。我试图限制对这些段的访问,因此该段是使用 rw-rw-r-- 创建的。这个想法是所有者和相关组将具有读/写访问权限,而“其他”将被限制为只读。
如果我 open_read_only 并手动遍历地图,这很好用。所有数据都存在于各个进程中。我在尝试使用 mymap->find() 或 mymap->at() 时遇到了问题,因为这两个函数都需要传递 basic_string(带分配器)。
当我尝试创建要在 find() 或 at() 中使用的 basic_string 时,出现访问冲突错误。
char_string tmpKey(searchKey, alloc_inst); // Access violation crash.
有没有办法在没有 basic_string 的情况下使用 find() 或 at()?还是有更好的方法来解决这个问题?
标题
typedef boost::interprocess::allocator<char, boost::interprocess::managed_shared_memory::segment_manager> CharAllocator;
typedef boost::container::basic_string<char, std::char_traits<char>, CharAllocator> char_string;
typedef char_string KeyType;
typedef char_string MappedType;
typedef std::pair<const char_string, char_string> ValueType;
typedef boost::interprocess::allocator<ValueType, boost::interprocess::managed_shared_memory::segment_manager> ShmemAllocator;
typedef boost::unordered_map<KeyType, MappedType, boost::hash<KeyType>, std::equal_to<KeyType>, ShmemAllocator> MyShmMap;
主要的
managed_shared_memory segment(open_read_only, "segment_name");
MyShmMap* mymap = segment.find<MyShmMap>("segment_name").first;
CharAllocator alloc_inst(segment.get_segment_manager());
char_string tmpKey(searchKey, alloc_inst); // Access violation crash.
MyShmMap::iterator it = mymap->find(tmpKey);
if (it != mymap->end()) {
auto value = mymap->at(tmpKey);
// etc
解决方案
您永远不会检查指针mymap
是否为空。
如果我们确保它存在,首先执行这个(一次):
// assuming this exists
Segment s(bip::open_or_create, "segment_name", 10 * 1024);
s.find_or_construct<MyShmMap>("segment_name")(s.get_segment_manager());
然后一切正常:Live On Coliru
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/unordered_map.hpp>
#include <boost/functional.hpp>
namespace bip = boost::interprocess;
namespace bc = boost::container;
using Segment = bip::managed_shared_memory;
using Mgr = Segment::segment_manager;
template <typename T> using Alloc = bip::allocator<T, Segment::segment_manager>;
template <typename K, typename V>
using UnorderedMap = boost::unordered_map<K, V, boost::hash<K>, //
std::equal_to<K>,
Alloc<std::pair<K const, V>>>;
using String = bc::basic_string<char, std::char_traits<char>, Alloc<char>>;
using MyShmMap = UnorderedMap<String, String>;
int main() {
{
// assuming this exists
Segment s(bip::open_or_create, "segment_name", 10 * 1024);
s.find_or_construct<MyShmMap>("segment_name")(s.get_segment_manager());
}
Segment segment(bip::open_read_only, "segment_name");
MyShmMap* mymap = segment.find<MyShmMap>("segment_name").first;
auto it = mymap->find(String("test", segment.get_segment_manager()));
if (it != mymap->end()) {
auto const& value = it->second;
}
}
我也借此机会
- 清理你的 type-def 以实现可重用性
- 请注意,使用
.at
after.find
非常浪费。这特别浪费,因为您使用 /shared/ 字符串作为键。
智能高效
您可以通过使用与字符串视图兼容的哈希/相等比较器并使用高级查找来真正提高性能:
template <typename K, typename V, typename Hash = boost::hash<K>,
typename EqCmp = std::equal_to<K>>
using UnorderedMap = boost::unordered_map<K, V, //
Hash, EqCmp, Alloc<std::pair<K const, V>>>;
using MyShmMap = UnorderedMap<String, String, boost::hash<std::string_view>, std::equal_to<void>>;
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/unordered_map.hpp>
#include <boost/functional.hpp>
namespace bip = boost::interprocess;
namespace bc = boost::container;
using Segment = bip::managed_shared_memory;
using Mgr = Segment::segment_manager;
template <typename T> using Alloc = bip::allocator<T, Segment::segment_manager>;
template <typename K, typename V, typename Hash = boost::hash<K>,
typename EqCmp = std::equal_to<K>>
using UnorderedMap = boost::unordered_map<K, V, //
Hash, EqCmp, Alloc<std::pair<K const, V>>>;
using String = bc::basic_string<char, std::char_traits<char>, Alloc<char>>;
using MyShmMap = UnorderedMap<String, String, boost::hash<std::string_view>, std::equal_to<void>>;
#include <string_view>
#include <iostream>
#include <iomanip>
int main()
{
{
// assuming this exists
Segment s(bip::open_or_create, "segment_name", 10 * 1024);
auto* m = s.get_segment_manager();
s.find_or_construct<MyShmMap>("segment_name")(m) //
->emplace(std::piecewise_construct, //
std::tuple("stuff", m), //
std::tuple("lives here", m));
}
Segment segment(bip::open_read_only, "segment_name");
MyShmMap* mymap = segment.find<MyShmMap>("segment_name").first;
auto hash = mymap->hash_function();
auto eq = mymap->key_eq();
if (auto it = mymap->find("stuff", hash, eq); it != mymap->end()) {
auto const& [k,v] = *it;
std::cout << std::quoted(k.c_str()) << " -> " << std::quoted(v.c_str()) << "\n";
}
}
哪个打印
"stuff" -> "lives here"
樱桃在上面
为了减少分配器的丑陋,例如:
Segment s(bip::open_or_create, "segment_name", 10 * 1024);
auto* m = s.get_segment_manager();
s.find_or_construct<MyShmMap>("segment_name")(m) //
->emplace(std::piecewise_construct, //
std::tuple("stuff", m), //
std::tuple("lives here", m));
考虑范围分配器:
template <typename T> using Alloc = bc::scoped_allocator_adaptor< //
bip::allocator<T, Segment::segment_manager>>;
现在容器在使用分配器构造时传播分配器:
Segment s(bip::open_or_create, "segment_name", 10 * 1024);
auto& m = *s.find_or_construct<MyShmMap>("segment_name")(
s.get_segment_manager());
m.emplace("stuff", "lives here");
再次看到它住在 Coliru 上。
推荐阅读
- python-3.x - python中的df.dtypes显示了另一个让我困惑的dtype
- python - 如何在pygame中只播放一个音乐文件?
- c# - 如何自动化(从命令行)安装 Visual Studio Build Tools 构建环境,适用于 C++、.NET、C# 等
- r - 使用回归线和正态分布叠加制作ggplot
- html - 在 textarea 上使用 formControlName 时会导致输入延迟的原因是什么?
- windows - 任务计划程序 Windows Server 2019 - 任务未运行 ONSTART
- python-3.x - 在python中提取部分匹配的字符串
- scala - Scala 编程语言:b/w 的区别是什么:1) Var 不可变映射、Val 可变映射和 Var 可变映射?
- java - 如何根据数据高亮TextView中的单词
- python - 使用 .apply() 和 Range 函数在索引级别的 Pandas Dataframe 中创建列表