Вектор строки общей карты памяти - PullRequest
0 голосов
/ 10 октября 2018

Как добавить строку в вектор, содержащийся внутри карты?Структура - это карта (float, vector (string)), где карта находится в разделяемой памяти. Мой вопрос: если ключ == требуемый ключ, тогда добавить строку в вектор строк?

Ответы [ 2 ]

0 голосов
/ 10 октября 2018

Делать это в разделяемой памяти довольно сложно, на самом деле.

Если вы правильно настроите все распределители и добавите блокировку, вы, как правило, получите очень неуклюжий код, который трудно прочитать из-за всехРаспределитель распространяется вокруг.

Вы можете, однако, использовать адаптер распределителя выделения 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"
0 голосов
/ 10 октября 2018

Вы имеете в виду что-то вроде этого:

#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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...