You never check the pointer mymap is not null.
If we make sure that exists, by first executing this (once):
// assuming this exists
Segment s(bip::open_or_create, "segment_name", 10 * 1024);
s.find_or_construct<MyShmMap>("segment_name")(s.get_segment_manager());
Then it all works fine: 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;
}
}
I also took the opportunity to
- clean up your type-defs for re-usability
- note that using
.at after .find is very wasteful. It's especially wasteful since you used the /shared/ string as the key.
Smart And Efficient
You can really improve the performance by using a hash/equality comparer that is compatible with string views, and using the 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>>;
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, 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";
}
}
Which prints
"stuff" -> "lives here"
Cherry On Top
To reduce the ugly of allocators like:
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));
Consider scoped allocators:
template <typename T> using Alloc = bc::scoped_allocator_adaptor< //
bip::allocator<T, Segment::segment_manager>>;
Now the container propagates the allocator when using the allocator to construct:
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");
See it Live On Coliru again.