boost::interprocess 容器的容器不在共享内存中 [英] boost::interprocess Containers of containers NOT in shared memory

查看:27
本文介绍了boost::interprocess 容器的容器不在共享内存中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有 boost::interprocess 容器的容器 类型.但是我喜欢在我的进程内存中使用这个类也是一个普通的类.有人可以帮我编写一个不带参数的构造函数,以便在我当前的进程内存中初始化该类.

I have the example demo program with a boost::interprocess Containers of containers type. But I like to use the class also a normal class within my process memory. Can someone help me to write a constructor which takes no arguments to have the class initialized in my current process memory.

#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;
}

推荐答案

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

If you change the allocator type, you change the container (such is the nature of compile-time template instantiation).

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

Technically, you could devise a type-erased allocator (à la std::function or boost::any_iterator) but this would probably result in abysmal performance. Also, it would still require all the allocators to correspond in all the statically known properties, reducing flexibility.

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

In reality, I suggest just templatizing MyStruct on the Allocator type to be used for any embedded containers. Then specifically take such an allocator in the constructor:

// 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 << "
src ints: ", "; "));
    boost::copy(des->ints, std::ostream_iterator<int>(std::cout << "
des ints: ", "; "));
    std::cout << "
-------------------------";
    boost::copy(src->doubles, std::ostream_iterator<double>(std::cout << "
src doubles: ", "; "));
    boost::copy(des->doubles, std::ostream_iterator<double>(std::cout << "
des 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");
}

这篇关于boost::interprocess 容器的容器不在共享内存中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆