我需要使用boost的 managed_shared_memory 在共享内存中分配用户定义的结构,但我不确定如何正确地解决这个问题。看来,使其正常工作的关键是使用自定义allocators。我已经成功地使用一个简单的POD uint64_t类型来完成这项工作,但是当我尝试将更复杂的类型放在共享内存中时,事情变得更加复杂。我想在共享内存中放置一个简单结构的示例将是以下几行:
struct SharedMemStruct {
explicit SharedMemStruct() = default;
explicit SharedMemStruct(
const bool bField0,
const std::string& rField1,
const uint32_t& rField2)
: mField0(bField0)
, mField1(rField1)
, mField2(rField2)
{}
bool mField0;
std::string mField1;
uint32_t mField2;
};
使用POD类型我成功初始化了共享内存,如下所示(将64位共享值放在名为“FaultReport”的命名区域中,该区域可以与另一个进程共享。
// Remove shared memory on construction and destruction
struct shm_remove {
shm_remove() { shared_memory_object::remove("albfd_shared_mem"); }
~shm_remove() { shared_memory_object::remove("albfd_shared_mem"); }
} remover;
// create a new shared memory segment 2K size
managed_shared_memory managed_shm(create_only, "albfd_shared_mem", 2048);
// construct a FaultReport - default to no faults
auto pFaultWrapper = managed_shm.construct<UtlSharedIPCWrapper<uint64_t>>("FaultReport")(0);
在另一个需要访问上述FaultReport的过程中,这很简单,如下所示:
// create a new shared memory segment 2K size
managed_shared_memory managed_shm(open_only, "albfd_shared_mem");
// shared memory must exist in
shared_memory_object shm(open_only, "albfd_shared_mem", read_write);
// lookup the FaultReport shared memory wrapper
auto pFaultReport = managed_shm.find<UtlSharedIPCWrapper<uint64_t>>("FaultReport").first;
// initialize the bit-set from the current shared memory fault report
std::bitset<64> bitSet(pFaultReport->getSharedData());
UtlSharedIPCWrapper使我能够安全访问其数据类型T
template<typename T>
struct UtlSharedIPCWrapper {
private:
using upgradable_mutex_type = boost::interprocess::interprocess_upgradable_mutex;
mutable upgradable_mutex_type mMutex;
/*volatile*/ T mSharedData;
public:
// explicit struct constructor used to initialize directly from existing memory
explicit UtlSharedIPCWrapper(const T& rInitialValue)
: mSharedData(rInitialValue)
{}
T getSharedData() const {
boost::interprocess::sharable_lock<upgradable_mutex_type> lock(mMutex);
return mSharedData;
}
void setSharedData(const T& rSharedData) {
boost::interprocess::scoped_lock<upgradable_mutex_type> lock(mMutex);
// update the shared data copy mapped - scoped locked used if exception thrown
// a bit like the lock guard we normally use
this->mSharedData = rSharedData;
}
};
修改:
所以经过一些实验 - 特别是在意识到我的SharedIPCStruct
包含多个变量字符串字段(因此有效地需要指针或某些性质)之后,我在头文件中重写了结构并在下面显示了它。这里的关键似乎是使用boost的共享内存模型的某种特殊的stl替换字符串。为此,我为需要存储在我的结构中的字符串类型定义了以下内容:
using char_allocator = boost::interprocess::managed_shared_memory::allocator<char>::type;
using shm_string = boost::interprocess::basic_string<char, std::char_traits<char>, char_allocator>;
其中一个char_allocator作为最后一个参数传递到我的自定义结构中,以帮助将普通std::string
转换为这些新的shm_string
。我真的不明白这里的内容是什么,但它似乎有效 - 在这一点上逐步提升代码几乎是模板无意义。
#pragma once
// SYSTEM INCLUDES
#include <string>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
using char_allocator = boost::interprocess::managed_shared_memory::allocator<char>::type;
using shm_string = boost::interprocess::basic_string<char, std::char_traits<char>, char_allocator>;
// FORWARD DECLARATIONS
struct SharedIPCStruct {
explicit SharedIPCStruct (
const std::string& rString1,
const std::string& rString2,
const uint32_t& rHashValue,
const std::string& rString3,
const char_allocator& ca)
: mField1(rString1.cbegin(), rString1.cend(), ca)
, mField2(rString2.cbegin(), rString2.cend(), ca)
, mField3(rHashValue)
, mField4(rString3.cbegin(), rString3.cend(), ca)
{}
// note these are not std::strings
shm_string mField1;
shm_string mField2;
uint32_t mField3;
shm_string mField4;
};
现在有了这一切,分配共享内存结构就像这样简单:
char_allocator ca(managed_shm.get_allocator<char>());
// Create an object of SharedIPCStruct initialized to {"", "", 0, "", ca}
auto *pSHMStruct= managed_shm.construct<SharedIPCStruct>
("SharedIPCStruct") // name of the object
("", "", 0, "", ca); // ctor args
这很好用,在另一个过程中,我可以执行对应的搜索现有的SharedIPCStruct,其中包含以下内容
// lookup the SharedIPCStruct
auto *pSHMStruct = managed_shm.find<SharedIPCStruct>("SharedIPCStruct").first;
但问题仍然存在,我无法在共享内存中构建UtlSharedIPCWrapper<SharedIPCStruct>
。我想这样做是为了安全访问SharedIPCStruct
。
由于UtlSharedIPCWrapper
的模板参数类型是POD类型,因此编译并运行:
auto pFaultWrapper = managed_shm.construct<UtlSharedIPCWrapper<uint64_t>>("FaultReport")(0);
但是,我替换
// Create an object of SharedIPCStruct initialized to {"", "", 0, "", ca}
auto *pSHMStruct= managed_shm.construct<SharedIPCStruct>
("SharedIPCStruct") // name of the object
("", "", 0, "", ca); // ctor args
使用模板化的包装器,就像我上面为包装自定义数据结构的POD类型所做的那样
// Create an object of SharedIPCStruct initialized to {"", "", 0, "", ca}
auto *pSHMStruct= managed_shm.construct<UtlSharedIPCWrapper<SharedIPCStruct>>
("SharedIPCStruct") // name of the object
("", "", 0, "", ca); // ctor args
我收到了大量无法理解的错误。有人可以解释这里发生了什么以及我应该如何正确地写这个以便使用我的包装器。还有一个必须应用于共享内存中的自定义数据结构的一般规则(如果有的话)是什么?我发现std :: strings无法使用但是浮点数等等和其他类型。
main.cpp
1>c:\main\extlibs\boost_1_60_0\boost\interprocess\detail\named_proxy.hpp(83): error C2661: 'UtlSharedIPCWrapper<SharedIPCStruct>::UtlSharedIPCWrapper': no overloaded function takes 5 arguments
1> c:\main\extlibs\boost_1_60_0\boost\interprocess\detail\named_proxy.hpp(71): note: see reference to function template instantiation 'void boost::interprocess::ipcdetail::CtorArgN<T,false,const char (&)[1],const char (&)[1],int,const char (&)[1],char_allocator &>::construct<0,1,2,3,4>(void *,boost::interprocess::ipcdetail::false_,const boost::container::container_detail::index_tuple<0,1,2,3,4> &)' being compiled
1> with
1> [
1> T=UtlSharedIPCWrapper<SharedIPCStruct>
1> ]
1> c:\main\extlibs\boost_1_60_0\boost\interprocess\detail\named_proxy.hpp(71): note: see reference to function template instantiation 'void boost::interprocess::ipcdetail::CtorArgN<T,false,const char (&)[1],const char (&)[1],int,const char (&)[1],char_allocator &>::construct<0,1,2,3,4>(void *,boost::interprocess::ipcdetail::false_,const boost::container::container_detail::index_tuple<0,1,2,3,4> &)' being compiled
1> with
1> [
1> T=UtlSharedIPCWrapper<SharedIPCStruct>
1> ]
1> c:\main\extlibs\boost_1_60_0\boost\interprocess\detail\named_proxy.hpp(68): note: while compiling class template member function 'void boost::interprocess::ipcdetail::CtorArgN<T,false,const char (&)[1],const char (&)[1],int,const char (&)[1],char_allocator &>::construct_n(void *,size_t,size_t &)'
1> with
1> [
1> T=UtlSharedIPCWrapper<SharedIPCStruct>
1> ]
1> c:\main\extlibs\boost_1_60_0\boost\interprocess\detail\named_proxy.hpp(128): note: see reference to class template instantiation 'boost::interprocess::ipcdetail::CtorArgN<T,false,const char (&)[1],const char (&)[1],int,const char (&)[1],char_allocator &>' being compiled
1> with
1> [
1> T=UtlSharedIPCWrapper<SharedIPCStruct>
1> ]
1> c:\main\dlmu\albfd-0339.1\src\albfd\main.cpp(224): note: see reference to function template instantiation 'T *boost::interprocess::ipcdetail::named_proxy<boost::interprocess::segment_manager<CharType,MemoryAlgorithm,IndexType>,T,false>::operator ()<const char(&)[1],const char(&)[1],int,const char(&)[1],char_allocator&>(const char (&)[1],const char (&)[1],int &&,const char (&)[1],char_allocator &) const' being compiled
1> with
1> [
1> T=UtlSharedIPCWrapper<SharedIPCStruct>,
1> CharType=char,
1> MemoryAlgorithm=boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,ptrdiff_t,uintptr_t,0>,0>,
1> IndexType=boost::interprocess::iset_index
1> ]
1> c:\main\dlmu\albfd-0339.1\src\albfd\main.cpp(224): note: see reference to function template instantiation 'T *boost::interprocess::ipcdetail::named_proxy<boost::interprocess::segment_manager<CharType,MemoryAlgorithm,IndexType>,T,false>::operator ()<const char(&)[1],const char(&)[1],int,const char(&)[1],char_allocator&>(const char (&)[1],const char (&)[1],int &&,const char (&)[1],char_allocator &) const' being compiled
1> with
1> [
1> T=UtlSharedIPCWrapper<SharedIPCStruct>,
1> CharType=char,
1> MemoryAlgorithm=boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,boost::interprocess::offset_ptr<void,ptrdiff_t,uintptr_t,0>,0>,
1> IndexType=boost::interprocess::iset_index
1> ]