Structures and vectors in Boost Shared Memory

前端 未结 1 1133
我在风中等你
我在风中等你 2020-12-19 09:29

I am new to Boost. I have the following structure and want to store it in shared memory using Boost.

struct InData{
    int x,y,h,w;
    char* lbl;
};
         


        
1条回答
  •  执笔经年
    2020-12-19 09:53

    You can easily store UDT in there, Boost's interprocess allocator will do the magic for you. However, storing raw-pointers is not gonna work.

    So, let's start off with a sample without raw pointers:

    struct InData {
        int x = 0, y = 0, h = 0, w = 0;
        shared_string label;
    };
    

    Assuming shared_string is already define like e.g.

    using shared_string = bip::basic_string, bip::allocator>;
    

    I like to separate my datastructures from the choice of allocator, so I might write it more generically:

    template  >
    struct BasicInData {
        BasicInData(Alloc alloc = {}) : label(alloc) { }
    
        int x = 0, y = 0, h = 0, w = 0;
        string label;
    };
    

    Now, you can "freely" add this to a shared memory/memory mapped segment. I usually set up some typedefs in a namespace:

    using InData = BasicInData<>; // just heap allocated
    
    namespace Shared {
        using segment                      = bip::managed_mapped_file; // or managed_shared_memory
        using segment_manager              = segment::segment_manager;
    
        template  using alloc  = bip::allocator;
        template  using vector = bip::vector >;
    
        using InData = BasicInData >; // shared memory version 
    }
    

    Now you can use the vector from Shared in a managed memory segment:

    segment smt(bip::open_or_create, "data.bin", 10u<<20); // 10 MiB
    vector* v = smt.find_or_construct >("InDataVector")(smt.get_segment_manager());
    

    This creates a vector inside a file of 10 MiB.

    Full Demo Live

    I've extended the demo with some functions to generate random data. The program looks like:

    int main() {
        Shared::segment smt(bip::open_or_create, "data.bin", 10u<<20); // 10 MiB
        auto& data = Shared::locate(smt);
    
        std::generate_n(std::back_inserter(data), 2, [&smt] { return generate(smt.get_segment_manager()); });
    
        for(auto& d : data) {
            std::cout << d << "\n";
        }
    }
    

    Each time it's run it will add two randomly generated InData structures. First time output could be e.g.

    InData { 99, 7, 71, 65, nwlsovjiwv }
    InData { 16, 51, 33, 34, nuujiblavs }
    

    Then, second time will show the existing records plus two newly generated lines:

    InData { 99, 7, 71, 65, nwlsovjiwv }
    InData { 16, 51, 33, 34, nuujiblavs }
    InData { 49, 26, 81, 30, snhcvholti }
    InData { 48, 66, 19, 8, xtididuegs }
    

    Live On Coliru

    #include 
    
    #include  // use for Coliru
    #include    // boost/containers/vector.hpp
    #include    // boost/containers/string.hpp
    #include 
    #include 
    
    namespace bip = boost::interprocess;
    
    template  >
    struct BasicInData {
        using string = bip::basic_string, typename Alloc::template rebind::other>;
    
        BasicInData(Alloc alloc = {}) :
            label(alloc) 
        { }
    
        template 
        BasicInData(int x, int y, int h, int w, T&& label, Alloc alloc = {}) :
            x(x), y(y), h(h), w(w), label(std::forward(label), alloc) 
        { }
    
        int x = 0, y = 0, h = 0, w = 0;
        string label;
    };
    
    using InData = BasicInData<>; // just heap allocated
    
    namespace Shared {
        using segment                      = bip::managed_mapped_file;           // or managed_shared_memory
        using segment_manager              = segment::segment_manager;
    
        template  using alloc  = bip::allocator;
        template  using vector = bip::vector >;
    
        using InData = BasicInData >; // shared memory version 
    
        vector& locate(segment& smt) {
            auto* v = smt.find_or_construct >("InDataVector")(smt.get_segment_manager());
            assert(v);
            return *v;
        }
    }
    
    static std::mt19937 prng { std::random_device{} () };
    
    // ugly quick and dirty data generator
    template 
    Shared::InData generate(SegmentManager const& sm) {
        static std::uniform_int_distribution coord_dist(1,100);
        static std::uniform_int_distribution char_dist('a', 'z');
        char buf[11] = { 0 };
    
        auto rand_coord = [] { return coord_dist(prng); };
        auto gen_ch     = [] { return char_dist(prng); };
        auto rand_label = [&] { std::generate(std::begin(buf), std::end(buf)-1, gen_ch); return buf; };
    
        return { rand_coord(), rand_coord(), rand_coord(), rand_coord(), rand_label(), sm }; 
    }
    
    // demo:
    
    template 
    static std::ostream& operator<<(std::ostream& os, BasicInData const& d) {
        return os << "InData { " << d.x << ", " << d.y << ", " <<
                                    d.w << ", " << d.h << ", " << d.label << " }";
    }
    
    int main() {
        Shared::segment smt(bip::open_or_create, "data.bin", 10u<<10); // 10 Kb for coliru
        auto& data = Shared::locate(smt);
    
        std::generate_n(std::back_inserter(data), 2, [&smt] { return generate(smt.get_segment_manager()); });
    
        for(auto& d : data) {
            std::cout << d << "\n";
        }
    }
    

    0 讨论(0)
提交回复
热议问题