如何为Boost多索引容器实现共享内存与映射文件的通用分配器封装?
如何用分配器包装类适配Boost多索引容器的两种共享内存类型?
当然可以!完全不用定义两套几乎一样的容器类型,我们可以通过通用分配器模板+模板化多索引容器的方式,轻松适配bip::managed_mapped_file和bip::managed_shared_memory这两种内存类型。
核心思路
Boost Interprocess里的这两种内存段类型,它们的段管理器(segment_manager)都遵循相同的接口规范。这意味着我们可以用模板来抽象内存段的类型差异,让分配器和容器自动适配对应的内存类型。
具体实现步骤
定义通用分配器模板
我们先写一个能接受任意内存段类型的分配器模板,它会自动提取对应内存段的段管理器类型:template <typename T, typename MemorySegment> using GenericAllocator = bip::allocator<T, typename MemorySegment::segment_manager>;模板化多索引容器
把你的MyGlobalHash改成模板,依赖内存段类型,这样它就能自动使用上面的通用分配器:template <typename MemorySegment> using MyGlobalHash = boost::multi_index::multi_index_container< My_Key, My_Key_hash_indices, GenericAllocator<My_Key, MemorySegment> >;根据配置切换内存类型
你可以用std::conditional_t在编译时根据配置选择对应的内存段类型,不用写两套逻辑:// 示例配置:true用映射文件,false用共享内存 const bool use_mapped_file = false; // 自动选择内存段类型 using SelectedMemorySegment = std::conditional_t<use_mapped_file, bip::managed_mapped_file, bip::managed_shared_memory>; // 得到最终的容器类型 using SelectedGlobalHash = MyGlobalHash<SelectedMemorySegment>;
完整可运行代码示例
#include <boost/multi_index_container.hpp> #include <boost/multi_index/hashed_index.hpp> #include <boost/multi_index/member.hpp> #include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/managed_mapped_file.hpp> #include <type_traits> namespace bip = boost::interprocess; namespace bmi = boost::multi_index; // 示例My_Key结构体定义 struct My_Key { int id; std::string name; }; // 多索引容器的索引定义 using My_Key_hash_indices = bmi::indexed_by< bmi::hashed_unique< bmi::member<My_Key, int, &My_Key::id> > >; // 通用分配器模板,适配任意内存段类型 template <typename T, typename MemorySegment> using GenericAllocator = bip::allocator<T, typename MemorySegment::segment_manager>; // 模板化的多索引容器 template <typename MemorySegment> using MyGlobalHash = bmi::multi_index_container< My_Key, My_Key_hash_indices, GenericAllocator<My_Key, MemorySegment> >; int main() { // 配置开关:切换为true即可使用managed_mapped_file const bool use_mapped_file = false; // 根据配置选择内存段类型 using SelectedMemorySegment = std::conditional_t<use_mapped_file, bip::managed_mapped_file, bip::managed_shared_memory>; using SelectedHash = MyGlobalHash<SelectedMemorySegment>; // 初始化内存段(名称和大小按需调整) SelectedMemorySegment segment( bip::open_or_create, use_mapped_file ? "my_mapped_storage" : "my_shared_storage", 1024 * 1024 // 1MB内存空间 ); // 构造或获取容器实例 auto* hash_container = segment.find_or_construct<SelectedHash>("my_global_hash")( segment.get_segment_manager() ); // 测试插入数据 hash_container->insert({1, "test_item"}); return 0; }
方案优势
- 彻底消除代码冗余:不用重复定义两套几乎一致的容器类型
- 编译时类型选择:通过
std::conditional_t实现配置驱动的类型切换,运行时无额外开销 - 兼容性强:完全利用Boost Interprocess的接口一致性,后续如果有其他内存段类型也能轻松扩展
内容的提问来源于stack exchange,提问作者yaron
相关产品推荐
相关产品推荐

