我试图在进程间无序映射中保存共享指针(boost interprocess)作为值。在我的测试程序中,我插入了大约100个元素。每个元素都有一个字符串作为键,shared_ptr作为值。 shared_ptr是指向复杂数据类型的指针。
第一个元素的创建和插入成功完成。但是,当我为第二个元素创建shared_ptr实例时,我得到一个异常。我得到以下例外:
错误:boost :: interprocess_exception :: library_error。 错误代码:错误的文件描述符。 native-error:0。
我已粘贴下面的代码。任何帮助表示赞赏。感谢。
的defs.h
// basic shared memory defs.
#pragma once
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/string.hpp>
namespace bip = boost::interprocess;
namespace ip {
namespace shmem {
using segment = bip::managed_shared_memory;
using segment_manager = segment::segment_manager;
using void_allocator = bip::allocator<void, segment_manager>;
using char_allocator = bip::allocator<char, segment_manager>;
using int_allocator = bip::allocator<int, segment_manager>;
using double_allocator = bip::allocator<double, segment_manager>;
using size_t_allocator = bip::allocator<size_t, segment_manager>;
using string = bip::basic_string<char, std::char_traits<char>, char_allocator>;
} // namespace shmem
} // namespace ip
地图value.h
#pragma once
#include <boost/interprocess/smart_ptr/deleter.hpp>
#include <boost/interprocess/smart_ptr/shared_ptr.hpp>
#include <cassert>
#include "defs.h"
namespace ip
{
template <typename ValueType>
class MapValue
{
public:
using MVType = MapValue<ValueType>;
typedef typename bip::deleter<MVType, shmem::segment_manager> MVDeleter;
typedef typename bip::managed_shared_ptr<MVType, shmem::segment>::type MapValuePtr;
MapValue(const shmem::void_allocator&, ValueType value=ValueType(), size_t=0);
MapValue(const MapValue& other);
MapValue& operator=(const MapValue& other);
MapValue(const MapValue&& other) noexcept;
MapValue& operator=(const MapValue&& other) noexcept;
void swap(const MapValue& other) noexcept;
size_t GetTimestamp() const { return mTimestamp; }
ValueType GetValue() const { return mValue; }
private:
size_t mTimestamp;
ValueType mValue;
};
} // namespace ip
map-value.cc
#include "map-value.h"
namespace ip
{
template <typename ValueType>
MapValue<ValueType>::MapValue(const shmem::void_allocator &void_allocator
, ValueType value, size_t expire_ts)
: mTimestamp(expire_ts)
, mValue(value, void_allocator)
{
}
template <typename ValueType>
MapValue<ValueType>::MapValue(const MapValue& other)
: mTimestamp(other.mTimestamp)
, mValue(other.mValue)
{
}
template <typename ValueType>
MapValue<ValueType>&
MapValue<ValueType>::operator=(const MapValue& other)
{
MapValue tmp(other);
swap(tmp);
return *this;
}
template <typename ValueType>
MapValue<ValueType>::MapValue(const MapValue&& other) noexcept
: mTimestamp(std::move(other.mTimestamp))
, mValue(std::move(other.mValue))
{
}
template <typename ValueType>
MapValue<ValueType>&
MapValue<ValueType>::operator=(const MapValue&& other) noexcept
{
auto tmp = std::move(other);
swap(tmp);
return *this;
}
template <typename ValueType>
void
MapValue<ValueType>::swap(const MapValue& other) noexcept
{
mTimestamp = other.mTimestamp;
mValue = other.mValue;
}
template class MapValue<shmem::string>;
} // namespace ip
unorderd_map_master.cc
#include <chrono>
#include <cstdlib>
#include <iostream>
#include <functional> //std::equal_to
#include <sstream>
#include <string.h>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/unordered_map.hpp> //boost::unordered_map
#include <boost/functional/hash.hpp> //boost::hash
#include "map-value.h"
using namespace boost::interprocess;
using namespace ip;
int
main ()
{
shared_memory_object::remove("MySharedMemory");
// Create shared memory
managed_shared_memory segment(create_only, "MySharedMemory", 1024*64);
// Note that unordered_map<Key, MappedType>'s value_type is
// std::pair<const Key, MappedType>, so the allocator must allocate a pair.
//
typedef int KeyType;
//typedef size_t MappedType;
typedef std::pair<const int, MapValue<shmem::string>::MapValuePtr> ValueType;
// Typedef the allocator
typedef allocator<ValueType, shmem::segment_manager> ShmemAllocator;
// Alias an unordered_map of ints that uses the previous STL-like allocator.
typedef boost::unordered_map<KeyType, MapValue<shmem::string>::MapValuePtr
, boost::hash<KeyType>, std::equal_to<KeyType>
, ShmemAllocator> SharedHashMap;
// Construct a shared memory hash map.
// Note that the first parameter is the initial bucket count and
// after that, the hash function, the equality function and the allocator
SharedHashMap *hashmap = segment.construct<SharedHashMap>("SharedHashMap") //object name
(4 // bucket count
, boost::hash<KeyType>() // hash func
, std::equal_to<KeyType>() // equality func
, segment.get_allocator<ValueType>()); //allocator instance
int i;
std::string test("test");
using MVString = MapValue<shmem::string>;
using MVStringPtr = MVString::MapValuePtr;
using MVStringDeleter = MVString::MVDeleter;
shmem::void_allocator alloc_inst (segment.get_segment_manager());
try {
// Insert data in the hash map
for (i = 0; i < 100; ++i) {
// Create a shared pointer in shared memory
// pointing to a newly created object in the segment
std::ostringstream ostr;
ostr << test << i;
const uint64_t now = std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now().time_since_epoch()).count();
size_t ts = now + 60*1000000; // 60s from now.
shmem::string name(ostr.str().c_str(), alloc_inst);
std::cout << "created name: " << name << '\n';
MVStringPtr sh_ptr_instance =
make_managed_shared_ptr(segment.construct<MVString>("MVString")(alloc_inst
, name, ts), segment);
assert(sh_ptr_instance.use_count() == 1);
std::cout << "created shared_ptr" << '\n';
hashmap->insert(ValueType(i, sh_ptr_instance));
std::cout << "Inserting at " << i << ": "
<< "value: " << ostr.str() << ". "
<< "timestamp: " << ts << '\n';
}
}
catch (const bip::interprocess_exception& e) {
std::cout << "error: " << e.what() << ". "
<< "error-code: " << strerror(e.get_error_code()) << ". "
<< "error-msg: " << e.get_native_error() << ". " << '\n';
std::cout << "Error while inserting element #" << (i+1) << '\n';
shared_memory_object::remove("MySharedMemory");
std::exit(-1);
}
std::cout << i << " values inserted into shared memory" << '\n';
return 0;
}
unorder_map_slave.cc
#include <cstdlib>
#include <iostream>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/unordered_map.hpp> //boost::unordered_map
#include <functional> //std::equal_to
#include <boost/functional/hash.hpp> //boost::hash
#include "map-value.h"
using namespace boost::interprocess;
using namespace ip;
int
main (int argc, char *argv[])
{
using namespace boost::interprocess;
int c;
bool clear_shmem = false;
while ((c = getopt(argc, argv, "c")) != -1) {
switch(c) {
case 'c':
clear_shmem = true;
break;
default:
std::cout << "Invalid input params to " << argv[0] << '\n';
break;
}
}
try
{
managed_shared_memory segment(open_or_create, "MySharedMemory", 65536);
// Again the map<Key, MappedType>'s value_type is std::pair<const Key, MappedType>,
// so the allocator must allocate that pair.
typedef int KeyType;
//typedef size_t MappedType;
typedef std::pair<const int, MapValue<shmem::string>::MapValuePtr> ValueType;
// Assign allocator
typedef allocator<ValueType, managed_shared_memory::segment_manager> ShmemAllocator;
// The map
typedef boost::unordered_map<KeyType, MapValue<shmem::string>::MapValuePtr
, boost::hash<KeyType>, std::equal_to<KeyType>
, ShmemAllocator> SharedHashMap;
// Initialize the shared memory STL-compatible allocator
ShmemAllocator alloc_inst(segment.get_segment_manager());
// access the map in SHM through the offset ptr
SharedHashMap::iterator iter;
offset_ptr<SharedHashMap> m_pmap = segment.find<SharedHashMap>("SharedHashMap").first;
if (!m_pmap) {
std::cout << "Shared memory not initalized... Exiting..." << '\n';
std::exit(-1);
}
iter = m_pmap->begin();
std::cout<< "size: " << m_pmap->size();
using MVString = MapValue<shmem::string>;
using MVStringPtr = MVString::MapValuePtr;
using MVStringDeleter = MVString::MVDeleter;
for (; iter != m_pmap->end(); iter++) {
MapValue<shmem::string>::MapValuePtr val(iter->second);
std::cout << "\n " << iter->first << " : "
<< "value: " << val->GetValue() << ". "
<< "timestamp: " << val->GetTimestamp() << '\n';
}
std::cout<< "\n";
}
catch (const bip::interprocess_exception& e) {
std::cout << "error: " << e.what() << ". "
<< "error-code: " << strerror(e.get_error_code()) << ". "
<< "error-msg: " << e.get_native_error() << ". " << '\n';
shared_memory_object::remove("MySharedMemory");
}
if (clear_shmem) {
shared_memory_object::remove("MySharedMemory");
}
return 0;
}
答案 0 :(得分:0)
我已经找到了自己的答案。看起来共享指针的名称字符串必须是唯一的。
MVStringPtr sh_ptr_instance =
make_managed_shared_ptr(segment.construct<MVString>("MVString")(alloc_inst, name, ts), segment);
例如,上面代码中的字符串“MVString”必须是唯一的。我看到了错误,因为我正在创建多个具有相同名称的共享指针。使名称字符串唯一解决了我的问题。