【问题标题】:boost::interprocess Containers of containers NOT in shared memoryboost::interprocess 不在共享内存中的容器的容器
【发布时间】:2014-11-30 18:12:49
【问题描述】:

我有一个boost::interprocess Containers of containers 类型的示例演示程序。 但我喜欢在我的进程内存中使用该类也是一个普通类。 有人可以帮我编写一个不带参数的构造函数,以便在我当前的进程内存中初始化类。

#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <shmfw/serialization/interprocess_vector.hpp>
#include <stdlib.h>     /* srand, rand */
#include <time.h>       /* time */


using namespace boost::interprocess;
//Alias an STL-like allocator of ints that allocates ints from the segment
typedef allocator<int, managed_shared_memory::segment_manager>  ShmemAllocator;

//Alias a vector that uses the previous STL-like allocator
typedef vector<int, ShmemAllocator> MyVector;

typedef allocator<void, managed_shared_memory::segment_manager >                           void_allocator;

class MyStruct {
public:
    MyVector myVector;
    //Since void_allocator is convertible to any other allocator<T>, we can simplify
    //the initialization taking just one allocator for all inner containers.
    MyStruct ( const void_allocator &void_alloc )
        : myVector ( void_alloc )
    {}
    // Thats what I like to have       
    //MyStruct ()
    //    : myVector ( ?? )
    //{}
};

int main () {

    // I would like to have something like that working and also the shm stuff below
    // MyStruct x;


    managed_shared_memory segment;
    //A managed shared memory where we can construct objects
    //associated with a c-string
    try {
         segment =  managed_shared_memory( create_only, "MySharedMemory", 65536 );
    } catch (...){
        segment = managed_shared_memory( open_only, "MySharedMemory" );
    }

    //Initialize the STL-like allocator
    const ShmemAllocator alloc_inst ( segment.get_segment_manager() );

    MyStruct *myStruct_src =  segment.find_or_construct<MyStruct> ( "MyStruct" ) ( alloc_inst );
    srand (time(NULL));
    myStruct_src->myVector.push_back ( rand() );

    MyStruct *myStruct_des =  segment.find_or_construct<MyStruct> ( "MyStruct" ) ( alloc_inst );

    for ( size_t i = 0; i < myStruct_src->myVector.size(); i++ ) {
        std::cout << i << ": " << myStruct_src->myVector[i] << " = " << myStruct_des->myVector[i] << std::endl;
    if(myStruct_src->myVector[i] != myStruct_des->myVector[i]) {
      std::cout << "Something went wrong!" << std::endl;
    }
    }


    //segment.destroy<MyVector> ( "MyVector" );
    return 0;
}

【问题讨论】:

    标签: boost containers interprocess allocator


    【解决方案1】:

    如果你改变分配器类型,你就改变了容器(这就是编译时模板实例化的本质)。

    从技术上讲,您可以设计一个类型擦除的分配器(std::function 或 boost::any_iterator),但这可能会导致糟糕的性能。此外,它仍然需要所有分配器对应所有静态已知的属性,从而降低了灵活性。

    实际上,我建议在 Allocator 类型上模板化 MyStruct 以用于任何嵌入式容器。然后在构造函数中具体取这样一个分配器:

    // Variant to use on the heap:
    using HeapStruct  = MyStruct<std::allocator>;
    // Variant to use in shared memory:
    using ShmemStruct = MyStruct<BoundShmemAllocator>;
    

    演示程序:

    #include <boost/interprocess/containers/vector.hpp>
    #include <boost/interprocess/allocators/allocator.hpp>
    #include <boost/interprocess/managed_shared_memory.hpp>
    #include <boost/range/algorithm.hpp>
    #include <iostream>
    #include <cassert>
    
    namespace bip = boost::interprocess;
    template <typename T> 
        using BoundShmemAllocator = bip::allocator<T, bip::managed_shared_memory::segment_manager>;
    
    ///////////////////////////////////////////////////////////////
    // Your MyStruct, templatized for an Allocator class template
    
    template <template<typename...> class Allocator>
    class MyStruct {
    public:
        bip::vector<int,    Allocator<int>    > ints;
        bip::vector<double, Allocator<double> > doubles;
    
        MyStruct(const Allocator<void>& void_alloc = {})
            : ints(void_alloc),
              doubles(void_alloc)
        {}
    };
    
    // Variant to use on the heap:
    using HeapStruct  = MyStruct<std::allocator>;
    // Variant to use in shared memory:
    using ShmemStruct = MyStruct<BoundShmemAllocator>;
    
    //
    ///////////////////////////////////////////////////////////////
    
    int main() {
        srand(time(NULL));
    
        // You can have something like this working: 
        HeapStruct x; // and also the shm stuff below
        std::generate_n(std::back_inserter(x.ints),    20, &std::rand);
        std::generate_n(std::back_inserter(x.doubles), 20, &std::rand);
    
        // A managed shared memory where we can construct objects
        bip::managed_shared_memory segment = bip::managed_shared_memory(bip::open_or_create, "MySharedMemory", 65536);
        BoundShmemAllocator<int> const shmem_alloc(segment.get_segment_manager());
    
        auto src = segment.find_or_construct<ShmemStruct>("MyStruct")(shmem_alloc);
        src->ints.insert(src->ints.end(),       x.ints.begin(),    x.ints.end());
        src->doubles.insert(src->doubles.end(), x.doubles.begin(), x.doubles.end());
    
        auto des = segment.find_or_construct<ShmemStruct>("MyStruct")(shmem_alloc);
    
        std::cout << "-------------------------";
        boost::copy(src->ints, std::ostream_iterator<int>(std::cout << "\nsrc ints: ", "; "));
        boost::copy(des->ints, std::ostream_iterator<int>(std::cout << "\ndes ints: ", "; "));
        std::cout << "\n-------------------------";
        boost::copy(src->doubles, std::ostream_iterator<double>(std::cout << "\nsrc doubles: ", "; "));
        boost::copy(des->doubles, std::ostream_iterator<double>(std::cout << "\ndes doubles: ", "; "));
    
        assert(src->ints.size()    == des->ints.size());
        assert(src->doubles.size() == des->doubles.size());
        assert(boost::mismatch(src->ints,    des->ints)    == std::make_pair(src->ints.end(),    des->ints.end()));
        assert(boost::mismatch(src->doubles, des->doubles) == std::make_pair(src->doubles.end(), des->doubles.end()));
    
        segment.destroy<ShmemStruct>("MyStruct");
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-20
    • 2019-12-17
    • 2020-10-19
    • 1970-01-01
    • 2012-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多