boost::interprocess scoped_allocator AND 不在共享内存中的容器的容器

Posted

技术标签:

【中文标题】boost::interprocess scoped_allocator AND 不在共享内存中的容器的容器【英文标题】:boost::interprocess scoped_allocator AND Containers of containers NOT in shared memory 【发布时间】:2015-04-20 21:42:31 【问题描述】:

我在boost::interprocess Containers of containers NOT in shared memory 和How to I create a boost interprocess vector of interprocess containers 中也有类似的问题,但这次我喜欢在堆和共享内存上使用我的类,它使用 scoped_allocator。

我的first question 的解决方案是使用具有分配器类型的模板类 在我的second previous question 中,事实证明,在共享内存中使用 scoped_allocator 和容器容器可以让生活更轻松。

现在我喜欢两者都有,这可能吗? 附上一个使用 scoped_allocator 的示例,但我不知道在这种情况下如何模板化类的分配器?

提前致谢:-)

马库斯

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/container/scoped_allocator.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/algorithm/string.hpp>

namespace bi = boost::interprocess;
namespace bc = boost::container;

typedef bi::managed_shared_memory::segment_manager                         segment_manager_t;
typedef bc::scoped_allocator_adaptor<bi::allocator<void, segment_manager_t> >  void_allocator;

class CheckList 
typedef void_allocator::rebind<double>::other       double_allocator;
typedef bc::vector<double, double_allocator>         double_vector;
public:
    double_vector values;

    typedef void_allocator allocator_type;

    //Since void_allocator is convertible to any other allocator<T>, we can simplify
    //the initialization taking just one allocator for all inner containers.
    CheckList ( const allocator_type &void_alloc )
        :  values ( void_alloc ) 

    CheckList ( CheckList const& other, const allocator_type &void_alloc )
        :  values ( other.values, void_alloc ) 

    friend std::ostream &operator << ( std::ostream &os, const CheckList &o ) 
        for ( size_t i = 0; i < o.values.size(); i++ )  os << (i>0?", ":"") << o.values[i];
        return os;
    
;

class Lists 
typedef void_allocator::rebind<CheckList>::other      checklist_allocator;
typedef bc::vector<CheckList, checklist_allocator>    checklist_vector;

public:
    Lists ( const void_allocator &void_alloc )
        : checklists ( void_alloc )
    
    checklist_vector checklists;

    friend std::ostream &operator << ( std::ostream &os, const Lists &o ) 
        for ( size_t i = 0; i < o.checklists.size(); i++ ) os << o.checklists[i]  << std::endl;
        return os;
    
;


int main ( int argc, char **argv ) 


    if ( argc > 1 && (boost::iequals ( "clear", argv[1] ) || boost::iequals ( "c", argv[1] ) ) ) 
        std::cout << "Remove shared memory" << std::endl;
        bi::shared_memory_object::remove ( "MySharedMemory" );
    


    //Create shared memory
    bi::managed_shared_memory segment ( bi::open_or_create,"MySharedMemory", 16*1024*1024 );

    //An allocator convertible to any allocator<T, segment_manager_t> type
    void_allocator alloc_inst ( segment.get_segment_manager() );

    Lists *lists = segment.find_or_construct<Lists> ( "Lists" ) ( alloc_inst );
    if ( lists->checklists.size() != 10 ) 
        std::cout << "Create Data" << std::endl;
        lists->checklists.resize ( 10 );
        for ( size_t i = 0; i < lists->checklists.size(); i++ ) 
            lists->checklists[i].values.resize ( i+1 );
            for ( size_t j = 0; j < lists->checklists[i].values.size(); j++ ) 
                lists->checklists[i].values[j] = j;
            
        
     else 
        std::cout << "Data Exists" << std::endl;
    
    std::cout << *lists << std::endl;

【问题讨论】:

【参考方案1】:

嗯。我不确定挑战是什么,超越......是的,让我们将分配器作为模板参数,并定义

namespace Shared 
    typedef bi::managed_shared_memory::segment_manager                             segment_manager_t;
    typedef bc::scoped_allocator_adaptor<bi::allocator<void, segment_manager_t> >  void_allocator;
    using Lists = common::Lists<void_allocator>;


namespace Heap 
    typedef std::allocator<void> void_allocator;
    using Lists = common::Lists<void_allocator>;

所以,我继续并实际制作了转换构造函数:

Live On Coliru

namespace common 
    template <typename Alloc>
    class CheckList 
        typedef typename Alloc::template rebind<double>::other double_allocator;
        typedef bc::vector<double, double_allocator> double_vector;

    public:
        double_vector values;

        typedef Alloc allocator_type;
        CheckList(const allocator_type& void_alloc = allocator_type()) : values(void_alloc) 

        template <typename Alloc2>
        CheckList(CheckList<Alloc2> const& other, const allocator_type& void_alloc = allocator_type())
        : values(void_alloc)
        
            for(auto& v : other.values) values.emplace_back(v);
        

        friend std::ostream& operator<<(std::ostream& os, const CheckList& o) 
            for (size_t i = 0; i < o.values.size(); i++)
                os << (i?", ":"") << o.values[i];
            return os;
        
    ;

    template <typename Alloc>
    class Lists 
        typedef typename Alloc::template rebind<CheckList<Alloc> >::other checklist_allocator;

    public:
        typedef Alloc allocator_type;
        typedef bc::vector<CheckList<Alloc>, checklist_allocator> checklist_vector;

        template <typename Alloc2>
        Lists& operator=(Lists<Alloc2> const& other) 
            for(auto& cl : other.checklists) checklists.emplace_back(cl);
            return *this;
        

        Lists(const Alloc& void_alloc = allocator_type()) : checklists(void_alloc) 
        checklist_vector checklists;

        friend std::ostream& operator<<(std::ostream& os, const Lists& o) 
            for (size_t i = 0; i < o.checklists.size(); i++)
                os << o.checklists[i] << '\n';
            return os;
        
    ;

这意味着您现在可以拥有一个返回基于堆的集合并将其分配给相同的共享内存版本的函数:

Heap::Lists generate_local() 
    Heap::Lists lists;
    Heap::Lists::checklist_vector::value_type v;

    for (int i=0; i<10; ++i) 
        v.values.emplace_back(i+1);
        lists.checklists.push_back(v);
    

    return lists;


// later:

    Lists& lists = *segment.find_or_construct<Lists>("Lists")(alloc_inst);

    if (lists.checklists.size() != 10) 
        std::cout << "Create Data" << std::endl;
        auto x = generate_local();
        lists = std::move(x);
     

【讨论】:

以上是关于boost::interprocess scoped_allocator AND 不在共享内存中的容器的容器的主要内容,如果未能解决你的问题,请参考以下文章

在已锁定的互斥体上使用 boost::interprocess 条件变量

提升 scoped_lock 导致 CPU 消耗过多

Boost.Interprocess内存位置

boost::interprocess::string 转换为 char*

boost::interprocess_mutex 与进程本地 boost::mutex

boost::interprocess::interprocess_condition::wait 在等待时不会原子地解锁互斥锁