字符串共享内存映射的向量

时间:2018-10-10 11:25:04

标签: c++ boost shared-memory

如何将字符串附加到包含在map中的向量?结构是map(float,vector(string)),其中映射位于共享内存中。我的问题是如果key == desired key然后将字符串附加到字符串向量中?

2 个答案:

答案 0 :(得分:1)

您的意思是这样的吗?

#include <map>
#include <vector>
#include <string>
#include <iostream>

int main()
{
        std::map<float, std::vector<std::string>> m;

        m[.5f].emplace_back("First");
        m[.5f].emplace_back("Second");
        m[.0f].emplace_back("Hello");
        m[.0f].emplace_back("World");

        for(const auto& [key, value] : m)
        {
                std::cout << "Key: " << key << '\n';
                for(const auto& str : value)
                        std::cout << '\t' << str << '\n';
        }
        std::cout.flush();
        return 0;
}

答案 1 :(得分:1)

实际上,在共享内存中执行此操作非常困难。

如果正确分配所有分配器并添加锁定,通常会得到非常笨拙的代码,由于所有分配器都在传递,因此很难读取。

但是,您可以使用Boost的作用域分配器适配器,它将做很多(很多)魔术,使生活变得更好。

我认为下面的代码示例恰好可以达到最佳效果。

  

警告:这是基于多年尝试将其提交来的经验。如果您落在“魔术”的边界之外(主要是由于uses_allocator<>scoped_allocator_adaptor而引起的就地施工支持),您会发现它破裂了,您将编写许多手册构造函数/转换调用以使其工作。

Live On Coliru

#define DEMO
#include <iostream>
#include <iomanip>
#include <mutex>
#include <boost/interprocess/containers/map.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/managed_mapped_file.hpp> // For Coliru (doesn't support shared memory)
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/container/scoped_allocator.hpp>

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

namespace Shared {
    using Segment = bip::managed_mapped_file; // Coliru doesn't support bip::managed_shared_memory

    template <typename T> using Alloc = bc::scoped_allocator_adaptor<bip::allocator<T, Segment::segment_manager> >;
    template <typename V>
        using Vector = bip::vector<V, Alloc<V> >;
    template <typename K, typename V, typename Cmp = std::less<K> >
        using Map = bip::map<K, V, Cmp, Alloc<std::pair<K const, V> > >;

    using String = bip::basic_string<char, std::char_traits<char>, Alloc<char> >;

    using Mutex = bip::interprocess_mutex;
}

namespace Lib {
    using namespace Shared;
    struct Data {
        using Map = Shared::Map<float, Shared::Vector<Shared::String> >;

        mutable Mutex _mx;
        Map _map;

        template <typename Alloc> Data(Alloc alloc = {}) : _map(alloc) {}

        bool append(float f, std::string s) {
            std::lock_guard<Mutex> lk(_mx); // lock

            auto it = _map.find(f);
            bool const exists = it != _map.end();

#ifndef DEMO
            if (exists) {
                it->second.emplace_back(s);
            }
#else
            // you didn't specify this, but lets insert new keys here, if
            // only for the demo
            _map[f].emplace_back(s);
#endif
            return exists;
        }

        size_t size() const {
            std::lock_guard<Mutex> lk(_mx); // lock
            return _map.size();
        }

        friend std::ostream& operator<<(std::ostream& os, Data const& data) {
            std::lock_guard<Mutex> lk(data._mx); // lock

            for (auto& [f,v] : data._map) {
                os << f << " ->";
                for (auto& ss : v) {
                    os << " " << std::quoted(std::string(ss));
                }
                os << "\n";
            }

            return os;
        }
    };
}

struct Program {
    Shared::Segment msm { bip::open_or_create, "data.bin", 10*1024 };
    Lib::Data& _data = *msm.find_or_construct<Lib::Data>("data")(msm.get_segment_manager());

    void report() const {
        std::cout << "Map contains " << _data.size() << " entries\n" << _data;
    }
};

struct Client : Program {
    void run(float f) {
        _data.append(f, "one");
        _data.append(f, "two");
    }
};

int main() {
    {
        Program server;
        server.report();

        Client().run(.5f);
        Client().run(.6f);
    }

    // report again
    Program().report();
}

首次运行将打印:

Map contains 0 entries
Map contains 2 entries
0.5 -> "one" "two"
0.6 -> "one" "two"

第二次跑步:

Map contains 2 entries
0.5 -> "one" "two"
0.6 -> "one" "two"
Map contains 2 entries
0.5 -> "one" "two" "one" "two"
0.6 -> "one" "two" "one" "two"