std::vector满足Boost的容器需求。进程间分配器?

时间:2022-09-08 23:56:35

In boost::interprocess documentation it is said as requirement for containers to be stored in shared memory:

在boost:::进程间文档中,将容器存储在共享内存中的要求称为:

  1. STL containers may not assume that memory allocated with an allocator can be deallocated with other allocators of the same type. All allocators objects must compare equal only if memory allocated with one object can be deallocated with the other one, and this can only tested with operator==() at run-time.
  2. STL容器可能不认为分配程序分配的内存可以与相同类型的其他分配程序分配。只有当分配给一个对象的内存可以分配给另一个对象时,所有分配器对象才必须进行相等的比较,并且这只能在运行时使用operator==()进行测试。
  3. Containers' internal pointers should be of the type allocator::pointer and containers may not assume allocator::pointer is a raw pointer.
  4. 容器的内部指针应该是类型分配器::指针和容器不能假设分配器:::指针是一个原始指针。
  5. All objects must be constructed-destroyed via allocator::construct and allocator::destroy functions.
  6. 所有对象都必须通过分配器::构造和分配器:::销毁函数进行构造-销毁。

I am using gcc 4.7.1 with -std=c++11 (and boost 1.53). Is it safe to use the below defined ShmVector type?

我使用的是gcc 4.7.1和-std=c++11(和boost 1.53)。使用下面定义的ShmVector类型安全吗?

typedef boost::interprocess::allocator<int,
    boost::interprocess::managed_shared_memory::segment_manager>  ShmemAllocator;
typedef std::vector<int, ShmemAllocator> ShmVector;

I tried a dummy process which uses this type, and it looks it is working, but I am still not sure that the vector in gcc4.7.1 does satisfy all the requirements. I am especially not sure about the first requirement.

我尝试了一个使用这种类型的伪进程,它看起来是有效的,但是我仍然不确定gcc4.7.1中的向量是否满足所有的需求。我对第一个要求特别不确定。

#include <iostream>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <vector>
#include <cstdlib> //std::system

typedef boost::interprocess::allocator<int,
        boost::interprocess::managed_shared_memory::segment_manager>  ShmemAllocator;
typedef std::vector<int, ShmemAllocator> ShmVector;

int main(int argc, char *argv[])
{
    if(argc == 1){ //Parent process

        struct shm_remove
        {
            shm_remove() { boost::interprocess::shared_memory_object::remove("MySharedMemory"); }
            ~shm_remove(){ boost::interprocess::shared_memory_object::remove("MySharedMemory"); }
        } remover;

        //Create a new segment with given name and size
        boost::interprocess::managed_shared_memory segment(boost::interprocess::create_only,
                "MySharedMemory", 65536);

        //Initialize shared memory STL-compatible allocator
        const ShmemAllocator allocator(segment.get_segment_manager());

        ShmVector* v = segment.construct<ShmVector>("ShmVector")(allocator);
        v->push_back(1); v->push_back(2); v->push_back(3);

        //Launch child process
        std::string s(argv[0]); s += " child ";
        if(0 != std::system(s.c_str()))
            return 1;

    } else { // Child process

        //Open the managed segment
        boost::interprocess::managed_shared_memory segment(
                boost::interprocess::open_only, "MySharedMemory");

        //Find the vector using the c-string name
        ShmVector *v = segment.find<ShmVector>("ShmVector").first;

        for (const auto& i : *v) {
            std::cout << i << " ";
        }
        std::cout << std::endl;

    }
}

2 个解决方案

#1


0  

In C++ 11 allocator rules have slightly changed, but I don't think it affects your question.

在c++ 11分配器规则中有一些变化,但是我认为它不会影响您的问题。

You probably want to know first what standard says about it. But you'd actually want to check whether your specific STL implementation conforms to the standard and doesn't contain bugs.

你可能首先想知道标准是怎么说的。但是您实际上需要检查您的特定STL实现是否符合标准,并且不包含bug。

For the second part I'd strongly recommend going to sources of and just checking that, it's not that hard actually.

对于第二部分,我强烈建议大家去找资料来源,检查一下,其实并不难。

Also, you could write your tests to see if it's actually working properly:

另外,你可以写你的测试看看它是否真的工作正常:

  • Create custom allocator:
    • use some custom type as pointer, const pointer;
    • 使用一些自定义类型作为指针,const指针;
    • In construct(), destruct() count number of calls;
    • 在构造()中,析构()计数调用的数量;
  • 创建自定义分配器:使用一些自定义类型作为指针,const指针;在构造()中,析构()计数调用的数量;
  • Create YourCustomType to be used with the allocator which also counts number of constructions/destructions.
  • 创建您的自定义类型与分配程序一起使用,该分配器也计算结构/破坏的数量。
  • Now, create std::vetor<YourCustomType, YourCustomAllocator<YourCustomType>> instance, insert some elements, clear the vector, destroy it and see if:
    • number of construct() destruct() calls is equal to number of constructions destructions of YourCustomType.
    • 构造()破坏()调用的数量等于您定制类型的结构破坏数量。
    • typeid(YourCustomAllocator::pointer) == typeid(std::vetor<YourCustomType, YourCustomAllocator<YourCustomType>>::pointer)
    • 类型id(YourCustomAllocator::指针)= =类型id(std::vetor < YourCustomType,YourCustomAllocator < YourCustomType > >::指针)
  • 现在,创建std::vetor >实例,插入一些元素,清除向量,销毁它,看看:构造()destruction()调用的数量是否等于你的customtype的构造破坏的数量。类型id(YourCustomAllocator::指针)= =类型id(std::vetor < YourCustomType,YourCustomAllocator < YourCustomType > >::指针) ,>

That's how you can be sure that all restrictions apply.

这就是确保所有限制都适用的方法。

As for the first part of the question, here's an old C++ standard (not C++ 11).

对于问题的第一部分,这里有一个旧的c++标准(不是c++ 11)。

1 There's no way (properly implemented) vector will take an allocator out of nowhere. It'll use whatever allocator you provide, and will use it for everything. As for operator==, it is implemented in boost's allocator and thus it's boost's problem to make operator== work as they require. Although I wasn't able to find confirmation in the standard.

没有办法(正确实现)向量将不知道从哪里带出一个分配器。它将使用您提供的任何分配器,并将它用于一切。至于操作符==,它是在boost的分配器中实现的,因此boost的问题是使操作符==按他们的要求工作。虽然我在标准中找不到确认。

2 Unless there's a bug, std::vector<T, YourAllocator>::pointer should be allocator's pointer. cppreference.com says that, and the standard says that, (look for "Template class vector"):

除非有bug, std::vector ::指针应该是分配器的指针。cppreference.com是这样说的,标准是这样说的(寻找“模板类向量”): ,>

    typedef typename Allocator::pointer               pointer;
    typedef typename Allocator::const_pointer         const_pointer;

Although the same standard says this about allocators: Implementations of containers described in this International Standard are permitted to assume that their Allocator template parameter meets the following two additional requirements beyond those in Table 6.

尽管相同的标准对分配器来说是这样的:在这个国际标准中描述的容器的实现被允许假定它们的分配器模板参数满足以下两个额外的需求,超出了表6的要求。

--All instances of a given allocator type are required to be inter- changeable and always compare equal to each other.

——给定分配器类型的所有实例都必须是可互换的,并且总是相等地进行比较。

--The typedef members pointer, const_pointer, size_type, and differ- ence_type are required to be T*, T const*, size_t, and ptrdiff_t, respectively.

——typedef成员指针、const_pointer、size_type和different - ence_type分别为T*、T const*、size_t和ptrdiff_t。

So, actually standard doesn't allow using any pointer types, but my guess is that actual STL implementations will work.

因此,实际上标准不允许使用任何指针类型,但我猜想实际的STL实现会起作用。

3 Just check the std::vector<T>::clear() method implementation to see if allocator::destroy is called. Check std::vector<T>::resize() method's implementation to see if allocator::construct is used. I was not able to find requirement of calling destroy and construct in the standard.

只需检查std::vector ::clear()方法实现,看看是否调用了分配器:::destroy。检查std::vector ::resize()方法的实现,看看是否使用了分配器:::构造。我在标准中找不到调用销毁和构造的要求。

#2


0  

I think the answer is no. Because in practice (in C++98) and in theory (C++11 standard), std::vector pointer cannot be something else than T*.

我认为答案是否定的。因为在实践中(在c++ 98中)和理论上(c++ 11标准),std::矢量指针不可能是T*。

That is why boost::interprocess::vector<T> uses boost::container::vector<T, boost::interprocess::allocator<T>> (instead of std::vector<T, boost::interprocess::allocator<T>>).

这就是为什么boost:::interprocess: vector 使用boost::container: vector::vector >(而不是std: vector >)。 ,> ,>

#1


0  

In C++ 11 allocator rules have slightly changed, but I don't think it affects your question.

在c++ 11分配器规则中有一些变化,但是我认为它不会影响您的问题。

You probably want to know first what standard says about it. But you'd actually want to check whether your specific STL implementation conforms to the standard and doesn't contain bugs.

你可能首先想知道标准是怎么说的。但是您实际上需要检查您的特定STL实现是否符合标准,并且不包含bug。

For the second part I'd strongly recommend going to sources of and just checking that, it's not that hard actually.

对于第二部分,我强烈建议大家去找资料来源,检查一下,其实并不难。

Also, you could write your tests to see if it's actually working properly:

另外,你可以写你的测试看看它是否真的工作正常:

  • Create custom allocator:
    • use some custom type as pointer, const pointer;
    • 使用一些自定义类型作为指针,const指针;
    • In construct(), destruct() count number of calls;
    • 在构造()中,析构()计数调用的数量;
  • 创建自定义分配器:使用一些自定义类型作为指针,const指针;在构造()中,析构()计数调用的数量;
  • Create YourCustomType to be used with the allocator which also counts number of constructions/destructions.
  • 创建您的自定义类型与分配程序一起使用,该分配器也计算结构/破坏的数量。
  • Now, create std::vetor<YourCustomType, YourCustomAllocator<YourCustomType>> instance, insert some elements, clear the vector, destroy it and see if:
    • number of construct() destruct() calls is equal to number of constructions destructions of YourCustomType.
    • 构造()破坏()调用的数量等于您定制类型的结构破坏数量。
    • typeid(YourCustomAllocator::pointer) == typeid(std::vetor<YourCustomType, YourCustomAllocator<YourCustomType>>::pointer)
    • 类型id(YourCustomAllocator::指针)= =类型id(std::vetor < YourCustomType,YourCustomAllocator < YourCustomType > >::指针)
  • 现在,创建std::vetor >实例,插入一些元素,清除向量,销毁它,看看:构造()destruction()调用的数量是否等于你的customtype的构造破坏的数量。类型id(YourCustomAllocator::指针)= =类型id(std::vetor < YourCustomType,YourCustomAllocator < YourCustomType > >::指针) ,>

That's how you can be sure that all restrictions apply.

这就是确保所有限制都适用的方法。

As for the first part of the question, here's an old C++ standard (not C++ 11).

对于问题的第一部分,这里有一个旧的c++标准(不是c++ 11)。

1 There's no way (properly implemented) vector will take an allocator out of nowhere. It'll use whatever allocator you provide, and will use it for everything. As for operator==, it is implemented in boost's allocator and thus it's boost's problem to make operator== work as they require. Although I wasn't able to find confirmation in the standard.

没有办法(正确实现)向量将不知道从哪里带出一个分配器。它将使用您提供的任何分配器,并将它用于一切。至于操作符==,它是在boost的分配器中实现的,因此boost的问题是使操作符==按他们的要求工作。虽然我在标准中找不到确认。

2 Unless there's a bug, std::vector<T, YourAllocator>::pointer should be allocator's pointer. cppreference.com says that, and the standard says that, (look for "Template class vector"):

除非有bug, std::vector ::指针应该是分配器的指针。cppreference.com是这样说的,标准是这样说的(寻找“模板类向量”): ,>

    typedef typename Allocator::pointer               pointer;
    typedef typename Allocator::const_pointer         const_pointer;

Although the same standard says this about allocators: Implementations of containers described in this International Standard are permitted to assume that their Allocator template parameter meets the following two additional requirements beyond those in Table 6.

尽管相同的标准对分配器来说是这样的:在这个国际标准中描述的容器的实现被允许假定它们的分配器模板参数满足以下两个额外的需求,超出了表6的要求。

--All instances of a given allocator type are required to be inter- changeable and always compare equal to each other.

——给定分配器类型的所有实例都必须是可互换的,并且总是相等地进行比较。

--The typedef members pointer, const_pointer, size_type, and differ- ence_type are required to be T*, T const*, size_t, and ptrdiff_t, respectively.

——typedef成员指针、const_pointer、size_type和different - ence_type分别为T*、T const*、size_t和ptrdiff_t。

So, actually standard doesn't allow using any pointer types, but my guess is that actual STL implementations will work.

因此,实际上标准不允许使用任何指针类型,但我猜想实际的STL实现会起作用。

3 Just check the std::vector<T>::clear() method implementation to see if allocator::destroy is called. Check std::vector<T>::resize() method's implementation to see if allocator::construct is used. I was not able to find requirement of calling destroy and construct in the standard.

只需检查std::vector ::clear()方法实现,看看是否调用了分配器:::destroy。检查std::vector ::resize()方法的实现,看看是否使用了分配器:::构造。我在标准中找不到调用销毁和构造的要求。

#2


0  

I think the answer is no. Because in practice (in C++98) and in theory (C++11 standard), std::vector pointer cannot be something else than T*.

我认为答案是否定的。因为在实践中(在c++ 98中)和理论上(c++ 11标准),std::矢量指针不可能是T*。

That is why boost::interprocess::vector<T> uses boost::container::vector<T, boost::interprocess::allocator<T>> (instead of std::vector<T, boost::interprocess::allocator<T>>).

这就是为什么boost:::interprocess: vector 使用boost::container: vector::vector >(而不是std: vector >)。 ,> ,>