В boost::interprocess
Документация называется требованием хранения контейнеров в общей памяти:
operator==()
во время выполнения.allocator::pointer
и контейнеры могут не принять allocator::pointer
это необработанный указательallocator::construct
а также allocator::destroy
функции.Я использую GCC 4.7.1 с -std = c ++ 11 (и повысить 1,53). Безопасно ли использовать нижеуказанные ShmVector
тип?
typedef boost::interprocess::allocator<int,
boost::interprocess::managed_shared_memory::segment_manager> ShmemAllocator;
typedef std::vector<int, ShmemAllocator> ShmVector;
Я попробовал фиктивный процесс, который использует этот тип, и похоже, что он работает, но я все еще не уверен, что вектор в 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;
}
}
В C ++ 11 правила выделения немного изменились, но я не думаю, что это влияет на ваш вопрос.
Вы, вероятно, хотите сначала узнать, что говорит об этом стандарт. Но на самом деле вы хотите проверить, соответствует ли ваша конкретная реализация STL стандарту и не содержит ли ошибок.
Во второй части я настоятельно рекомендую обратиться к источникам и просто проверить это, на самом деле это не так сложно.
Кроме того, вы можете написать свои тесты, чтобы увидеть, действительно ли они работают правильно:
construct()
, destruct()
посчитать количество звонков;YourCustomType
для использования с распределителем, который также считает количество конструкций / разрушений.std::vetor<YourCustomType, YourCustomAllocator<YourCustomType>>
Например, вставить некоторые элементы, очистить вектор, уничтожить его и посмотреть, если:
construct()
destruct()
количество вызовов равно числу разрушений конструкций YourCustomType
,typeid(YourCustomAllocator::pointer) == typeid(std::vetor<YourCustomType, YourCustomAllocator<YourCustomType>>::pointer)
Таким образом, вы можете быть уверены, что все ограничения применяются.
Что касается первой части вопроса, вот старый стандарт C ++ (не C ++ 11).
1 Нет никакого способа (правильно реализованного) вектора, который вывезет распределитель из ниоткуда. Он будет использовать любой предоставленный вами распределитель и будет использовать его для всего. Что касается оператора ==, он реализован в распределителе boost и, таким образом, проблема boost заключается в том, чтобы оператор == работал так, как им требуется. Хотя я не смог найти подтверждение в стандарт.
2 Если нет ошибки, std::vector<T, YourAllocator>::pointer
должен быть указателем распределителя. cppreference.com говорит, что, и стандарт Говорит, что, (ищите «Вектор класса шаблона»):
typedef typename Allocator::pointer pointer;
typedef typename Allocator::const_pointer const_pointer;
Хотя тот же стандарт говорит об этом распределители:
Реализация контейнеров, описанных в этом международном стандарте
разрешено предполагать, что их параметр шаблона Allocator соответствует
следующие два дополнительных требования помимо тех, что приведены в таблице 6.
—Все экземпляры данного типа распределителя должны быть
изменчивы и всегда сравнивают друг с другом.
—Указатель членов typedef, const_pointer, size_type и Different-
Тип ence_type должен быть T *, T const *, size_t и ptrdiff_t,
соответственно.
Итак, на самом деле стандарт не позволяет использовать какие-либо типы указателей, но я предполагаю, что фактические реализации STL будут работать.
3 Просто проверьте std::vector<T>::clear()
реализация метода, чтобы увидеть, вызывается ли allocator :: destroy. Проверьте std::vector<T>::resize()
реализация метода, чтобы увидеть, используется ли allocator :: construct. Я не смог найти требование вызова уничтожить и построить в стандарт.
Я думаю, что ответ — нет. Потому что на практике (в C ++ 98) и в теории (стандарт C ++ 11), std::vector
указатель не может быть чем-то другим, чем T*
,
Поэтому boost::interprocess::vector<T>
использования boost::container::vector<T, boost::interprocess::allocator<T>>
(вместо std::vector<T, boost::interprocess::allocator<T>>
).