Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 字符串共享内存映射向量_C++_Boost_Shared Memory - Fatal编程技术网

C++ 字符串共享内存映射向量

C++ 字符串共享内存映射向量,c++,boost,shared-memory,C++,Boost,Shared Memory,如何将字符串附加到地图中包含的向量?结构是map(float,vector(string)),其中map位于共享内存中。我的问题是,如果key==所需的key,那么将string附加到字符串的向量中 你的意思是这样的: #include <map> #include <vector> #include <string> #include <iostream> int main() { std::map<float, std:

如何将字符串附加到地图中包含的向量?结构是map(float,vector(string)),其中map位于共享内存中。我的问题是,如果key==所需的key,那么将string附加到字符串的向量中

你的意思是这样的:

#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;
}
#包括
#包括
#包括
#包括
int main()
{
std::map m;
m[.5f]。向后放置(“第一”);
m[.5f]。向后放置(“第二”);
m[.0f]。向后放置(“你好”);
m[.0f]。向后放置(“世界”);
用于(常数自动和[键,值]:m)
{

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

如果所有的分配器都正确,并且添加了锁,通常会得到非常笨拙的代码,因为所有分配器都在传递,所以很难读取

然而,您可以使用Boost的作用域分配器适配器,它将发挥很多(很多)魔力,让生活变得更好

我认为下面的代码示例正好是最合适的

警告:这是建立在多年的经验基础上的。如果您刚好不在“魔法”的范围之内(主要是由于
使用\u分配器
作用域\u分配器\u适配器
)你会发现它崩溃了,你会编写很多手动构造函数/转换调用来让它工作

#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 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"

请花一些时间重新阅读,尤其是和。还有和。最后,不要忘记如何创建。映射是否在共享内存中并不重要,至少不是访问本身。但可能需要一个信号量或互斥来防止多个并行访问。使用浮点数进行相等比较几乎总是一个坏主意。@Rene为什么这不重要?我同意,在没有代码的情况下,我们只能从概念上讲。从概念上讲,这并不重要。但从技术上讲,它在很多细节上都很重要。人们往往忘记,虽然分配器是一个很好的抽象,但共享内存分配器必然是有状态的,而有状态分配器需要大量的li程序员提供的brary支持和支持。我已在一个进程中使用托管共享内存初始化和分配映射对象。我需要在另一个进程中向其中添加更多元素。需要扩展映射或向量。@Max这是非常简单的。如果没有高级机制,这些都不能转换为共享内存容器(作用域分配器),即使这样,它也绕过了构造参数转发机制的边缘。我将发布一个答案,只是为了说明……如果您面临挑战,您可以尝试以自然方式编写
不存在的分支(比如
\u map.emplace(f,{s});
,就像您通常能够编写的那样)当然,我的解决方案通过使用默认的
操作符[]
来欺骗这一点。
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"