基于Boost的interprocess库在文件(共享内存,mmap)上构造容器(Windows,Linux通用)
前言
本文简要阐述使用boost的interprocess在文件中构造容器的方法。在这里我们以vector为例,构造一个vector<int>。
所用到的文件
#include <boost/interprocess/allocators/node_allocator.hpp>
#include <boost/interprocess/managed_mapped_file.hpp>
#include <boost/interprocess/segment_manager.hpp>
#include <boost/interprocess/containers/vector.hpp>
我们分别需要上面的四个文件,分别是内存分配器,映射文件管理器,段管理器,容器。由于是在文件上构造容器,因此无法使用标准的内存分配器,必须得使用interprocess库提供的分配器。
类简化及重命名
namespace bipc = boost::interprocess;
using managed_mapped_file_t = bipc::managed_mapped_file;
using mapped_segment_manager_t = bipc::managed_mapped_file::segment_manager;
using allocator_t = bipc::node_allocator<int, managed_mapped_file_t>;
using vector_t = bipc::vector<int, allocator_t>;
使用using进行重命名比typedef要来的方便,尤其是在对模板重命名的时候。内存分配器是不知道在哪里进行内存分配的,因此需要传入段管理器,同样的vector需要指定内存分配器。
将文件映射到内存,并构造容器
managed_mapped_file_t mapped_file(bipc::open_or_create, "test.mmap", 1024*1024);
vector_t * pvec = mapped_file.find_or_construct<vector_t>("vec")(mapped_file.get_segment_manager());
pvec->push_back(1);
pvec->emplace_back(2);
//......
首先构造一个managed_mapped_file,以打开或者创建的形式,文件大小为1MB。然后调用find_or_construct函数构造容器即可。
容器内包含容器或者自定义类型该怎么办?
如果仅仅是简单类型的结构体或者类,如下即可:
struct User_1 {
int id;
int age;
};
using allocator_t = bipc::node_allocator<User_1, managed_mapped_file_t>;
using vector_t = bipc::vector<User_1, allocator_t>;
但如果自定义类型包括容器,则需要通过以下方式构造:
struct User_2 {
public:
User_2(const mapped_segment_manager_t& segment_manager): score(segment_manager) {};
int id;
int age;
bipc::vector<int, bipc::node_allocator<int, managed_mapped_file_t>> score;
};
using allocator_t = bipc::node_allocator<User_2, managed_mapped_file_t>;
using vector_t = bipc::vector<User_2, allocator_t>;
值得注意的是,必须得有构造函数辅组构造其中容器以传入分配器。此外boost::interprocess::string类不需要传入分配器,可以使用默认分配器进行分配。
文件扩充
mapped_file.flush();
mapped_file.grow(1024*1024);
mapped_file.~basic_managed_mapped_file();
new (&mapped_file) managed_mapped_file_t(bipc::open_or_create, "test.mmap", 2*1024*1024);
pvec = mapped_file.find_or_construct<vector_t>("vec")(mapped_file.get_segment_manager());
必须将文件释放掉再重新创建对象,并且容器通用需要重新调动构造器进行构造。