问题描述
我是Boost的新手.我具有以下结构,并希望使用Boost将其存储在共享内存中.
I am new to Boost. I have the following structure and want to store it in shared memory using Boost.
struct InData{
int x,y,h,w;
char* lbl;
};
反过来,此结构将存储在Vector中.大多数示例都讨论Vector的int或string数据类型.我想提供一个示例,说明如何将用户定义的数据类型存储到Boost共享内存中.
In-turn this structure will be stored in Vector. Most of example talk about int or string datatype for Vectors. I would like if anbody can provide an example how to store user defined data type into boost shared memory.
推荐答案
您可以轻松地在其中存储UDT,Boost的进程间分配器将为您解决问题.但是,无法存储原始指针.
You can easily store UDT in there, Boost's interprocess allocator will do the magic for you. However, storing raw-pointers is not gonna work.
因此,让我们从一个没有原始指针的示例开始:
So, let's start off with a sample without raw pointers:
struct InData {
int x = 0, y = 0, h = 0, w = 0;
shared_string label;
};
假设已经定义了shared_string
,例如
using shared_string = bip::basic_string<char, std::char_traits<char>, bip::allocator<char, SegmentManager>>;
我喜欢将我的数据结构与分配器的选择分开,所以我可以更一般地编写它:
I like to separate my datastructures from the choice of allocator, so I might write it more generically:
template <typename Alloc = std::allocator<char> >
struct BasicInData {
BasicInData(Alloc alloc = {}) : label(alloc) { }
int x = 0, y = 0, h = 0, w = 0;
string label;
};
现在,您可以自由"将其添加到共享的内存/内存映射段中.我通常在名称空间中设置一些typedef:
Now, you can "freely" add this to a shared memory/memory mapped segment. I usually set up some typedefs in a namespace:
using InData = BasicInData<>; // just heap allocated
namespace Shared {
using segment = bip::managed_mapped_file; // or managed_shared_memory
using segment_manager = segment::segment_manager;
template <typename T> using alloc = bip::allocator<T, segment_manager>;
template <typename T> using vector = bip::vector<T, alloc<T> >;
using InData = BasicInData<alloc<char> >; // shared memory version
}
现在,您可以在托管内存段中使用Shared
中的vector<InData>
:
Now you can use the vector<InData>
from Shared
in a managed memory segment:
segment smt(bip::open_or_create, "data.bin", 10u<<20); // 10 MiB
vector<InData>* v = smt.find_or_construct<vector<InData> >("InDataVector")(smt.get_segment_manager());
这将在10 MiB的文件内创建一个向量.
This creates a vector inside a file of 10 MiB.
我已经用一些功能扩展了演示程序,以生成随机数据.该程序如下所示:
I've extended the demo with some functions to generate random data. The program looks like:
int main() {
Shared::segment smt(bip::open_or_create, "data.bin", 10u<<20); // 10 MiB
auto& data = Shared::locate(smt);
std::generate_n(std::back_inserter(data), 2, [&smt] { return generate(smt.get_segment_manager()); });
for(auto& d : data) {
std::cout << d << "\n";
}
}
每次运行时,它将添加两个随机生成的InData
结构.第一次输出可能是例如
Each time it's run it will add two randomly generated InData
structures. First time output could be e.g.
InData { 99, 7, 71, 65, nwlsovjiwv }
InData { 16, 51, 33, 34, nuujiblavs }
然后,第二次将显示现有记录 plus 两条新生成的行:
Then, second time will show the existing records plus two newly generated lines:
InData { 99, 7, 71, 65, nwlsovjiwv }
InData { 16, 51, 33, 34, nuujiblavs }
InData { 49, 26, 81, 30, snhcvholti }
InData { 48, 66, 19, 8, xtididuegs }
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/managed_mapped_file.hpp> // use for Coliru
#include <boost/interprocess/containers/vector.hpp> // boost/containers/vector.hpp
#include <boost/interprocess/containers/string.hpp> // boost/containers/string.hpp
#include <iostream>
#include <random>
namespace bip = boost::interprocess;
template <typename Alloc = std::allocator<char> >
struct BasicInData {
using string = bip::basic_string<char, std::char_traits<char>, typename Alloc::template rebind<char>::other>;
BasicInData(Alloc alloc = {}) :
label(alloc)
{ }
template <typename T>
BasicInData(int x, int y, int h, int w, T&& label, Alloc alloc = {}) :
x(x), y(y), h(h), w(w), label(std::forward<T>(label), alloc)
{ }
int x = 0, y = 0, h = 0, w = 0;
string label;
};
using InData = BasicInData<>; // just heap allocated
namespace Shared {
using segment = bip::managed_mapped_file; // or managed_shared_memory
using segment_manager = segment::segment_manager;
template <typename T> using alloc = bip::allocator<T, segment_manager>;
template <typename T> using vector = bip::vector<T, alloc<T> >;
using InData = BasicInData<alloc<char> >; // shared memory version
vector<InData>& locate(segment& smt) {
auto* v = smt.find_or_construct<vector<InData> >("InDataVector")(smt.get_segment_manager());
assert(v);
return *v;
}
}
static std::mt19937 prng { std::random_device{} () };
// ugly quick and dirty data generator
template <typename SegmentManager>
Shared::InData generate(SegmentManager const& sm) {
static std::uniform_int_distribution<int> coord_dist(1,100);
static std::uniform_int_distribution<char> char_dist('a', 'z');
char buf[11] = { 0 };
auto rand_coord = [] { return coord_dist(prng); };
auto gen_ch = [] { return char_dist(prng); };
auto rand_label = [&] { std::generate(std::begin(buf), std::end(buf)-1, gen_ch); return buf; };
return { rand_coord(), rand_coord(), rand_coord(), rand_coord(), rand_label(), sm };
}
// demo:
template <typename Alloc>
static std::ostream& operator<<(std::ostream& os, BasicInData<Alloc> const& d) {
return os << "InData { " << d.x << ", " << d.y << ", " <<
d.w << ", " << d.h << ", " << d.label << " }";
}
int main() {
Shared::segment smt(bip::open_or_create, "data.bin", 10u<<10); // 10 Kb for coliru
auto& data = Shared::locate(smt);
std::generate_n(std::back_inserter(data), 2, [&smt] { return generate(smt.get_segment_manager()); });
for(auto& d : data) {
std::cout << d << "\n";
}
}
这篇关于Boost共享内存中的结构和向量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!