Boost 共享内存中的结构和向量
Structures and vectors in Boost Shared Memory
我是 Boost 新手。我有以下结构,想使用 Boost 将它存储在共享内存中。
struct InData{
int x,y,h,w;
char* lbl;
};
反过来这个结构将存储在Vector中。大多数示例都在谈论 Vectors 的 int 或 string 数据类型。我希望有人可以提供一个示例,说明如何将用户定义的数据类型存储到增强共享内存中。
您可以轻松地将 UDT 存储在那里,Boost 的进程间分配器将为您施展魔法。但是,存储原始指针是行不通的。
那么,让我们从一个没有原始指针的示例开始:
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>>;
我喜欢将我的数据结构与分配器的选择分开,所以我可能会写得更通用:
template <typename Alloc = std::allocator<char> >
struct BasicInData {
BasicInData(Alloc alloc = {}) : label(alloc) { }
int x = 0, y = 0, h = 0, w = 0;
string label;
};
现在,您可以 "freely" 将其添加到共享 memory/memory 映射段。我通常在命名空间中设置一些 typedefs:
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>
:
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 的文件中创建一个向量。
现场完整演示
我用一些函数扩展了演示以生成随机数据。该程序看起来像:
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
结构。第一次输出可能是
InData { 99, 7, 71, 65, nwlsovjiwv }
InData { 16, 51, 33, 34, nuujiblavs }
然后,第二次将显示现有记录加上两条新生成的行:
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 新手。我有以下结构,想使用 Boost 将它存储在共享内存中。
struct InData{
int x,y,h,w;
char* lbl;
};
反过来这个结构将存储在Vector中。大多数示例都在谈论 Vectors 的 int 或 string 数据类型。我希望有人可以提供一个示例,说明如何将用户定义的数据类型存储到增强共享内存中。
您可以轻松地将 UDT 存储在那里,Boost 的进程间分配器将为您施展魔法。但是,存储原始指针是行不通的。
那么,让我们从一个没有原始指针的示例开始:
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>>;
我喜欢将我的数据结构与分配器的选择分开,所以我可能会写得更通用:
template <typename Alloc = std::allocator<char> >
struct BasicInData {
BasicInData(Alloc alloc = {}) : label(alloc) { }
int x = 0, y = 0, h = 0, w = 0;
string label;
};
现在,您可以 "freely" 将其添加到共享 memory/memory 映射段。我通常在命名空间中设置一些 typedefs:
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>
:
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 的文件中创建一个向量。
现场完整演示
我用一些函数扩展了演示以生成随机数据。该程序看起来像:
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
结构。第一次输出可能是
InData { 99, 7, 71, 65, nwlsovjiwv }
InData { 16, 51, 33, 34, nuujiblavs }
然后,第二次将显示现有记录加上两条新生成的行:
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";
}
}