如何搜索存储在 Boost::managed_shared_memory 段中的 Boost::interprocess::map 作为 open_read_only?
How do I search a Boost::interprocess::map stored within a Boost::managed_shared_memory segment as open_read_only?
我有一个 Boost:interprocess::unordered_map,它有一个字符串类型的键和字符串类型的值。该地图存储在 managed_shared_memory 段中。我试图限制对这些段的访问,因此该段是使用 rw-rw-r-- 创建的。这个想法是所有者和相关组将具有 read/write 访问权限,并且 'other' 将被限制为只读。
如果我 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;
}
}
我也趁机
- 清理您的类型定义以实现可重用性
- 请注意,在
.find
之后使用 .at
非常浪费。因为您使用 /shared/ 字符串作为键,所以特别浪费。
智能高效
您可以通过使用与字符串视图兼容的 hash/equality 比较器并使用 advanced lookup:
来真正提高性能
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");
我有一个 Boost:interprocess::unordered_map,它有一个字符串类型的键和字符串类型的值。该地图存储在 managed_shared_memory 段中。我试图限制对这些段的访问,因此该段是使用 rw-rw-r-- 创建的。这个想法是所有者和相关组将具有 read/write 访问权限,并且 'other' 将被限制为只读。
如果我 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;
}
}
我也趁机
- 清理您的类型定义以实现可重用性
- 请注意,在
.find
之后使用.at
非常浪费。因为您使用 /shared/ 字符串作为键,所以特别浪费。
智能高效
您可以通过使用与字符串视图兼容的 hash/equality 比较器并使用 advanced lookup:
来真正提高性能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");