пользовательский распределитель, использующий перемещение для вектора потока

StackOverflow https://stackoverflow.com/questions/3804884

Вопрос

В настоящее время я изучаю параллелизм в C ++ и наткнулся на использование вектора потоков, который, как я полагаю, будет возможен в C ++ 0x.Однако мой текущий компилятор, похоже, не имеет реализации контейнеров с поддержкой перемещения, и поэтому я получаю ошибки, генерируемые из-за std::thread::thread(const std::thread&) удален, т. е. я могу использовать конструктор перемещения / назначение перемещения только с std::thread.

Прав ли я, думая, что мог бы обойти эту проблему, написав пользовательский распределитель, используя

void MyAllocator::construct (pointer p, reference val)
/* should be non-const reference to val because using move constructor? */
{
    new ((void*)p) T (std::move(val));
}

вместо того , чтобы

void allocator::construct (pointer p, const_reference val)
{
    new ((void*)p) T (val);
}

?Или какая-то другая вариация на эту тему (возможно, с использованием перегрузки MyAllocator::construct).

Примечание:В основном это кратковременное учебное упражнение и достаточно эффективная работа, позволяющая поиграться с потоками в контейнерах.Я бы только использовал MyAllocator в этом контексте.Однако, пожалуйста, также укажите мне на любые библиотеки, в которых это может быть реализовано, чтобы я мог покопаться в исходном коде.

Это было полезно?

Решение

Если ваш компилятор не предоставляет информацию о перемещении std::vector тогда вам придется написать свою собственную специализацию по std::vector<std::thread> вместо того, чтобы просто предоставлять пользовательский распределитель.Весь C ++03 vector интерфейс основан на копировании: push_back() копирует элементы в; resize() инициализирует пустые элементы с помощью Копировать элемента, переданного в качестве второго параметра (даже если это значение по умолчанию T()); resize(), reserve(), insert(), erase() и push_back() будет Копировать элементы, если вектор нуждается в перераспределении, или элементы, которые в противном случае нуждаются в перемещении, и так далее.

Это настолько распространенная проблема, что я включил такую специализацию в свой (коммерческий) просто::поток реализация std::thread.

Другие советы

Самый простой способ обойти эту проблему, чтобы выделить нити на кучу и манипулировать на них указателями.

Проверить Boost Pointer Container библиотека: boost::ptr_vector<std::thread> Мне кажется, что вы ищете.

Требование того, что контейнеры STD принимают только для копироваемых объектов, больше связаны с интерфейсами контейнеров C ++ 03, чем он делает с реализацией аллекатора. Например

vector<T> b(100);
vector<T> a;
a=b;
assert(a==b);

Стандарт уверяет нас A == B верно. Однако, если T не были скопированы, то в лучшем случае A = B не скомпилируется, в худшем случае a = b непределен. Более того,

a.push_back(T());

Может привести к выделению нового пространства, а под капотом есть копии, сделанные для нового базового хранения от старого.

Кроме того, в стандарте C ++ 03 нет ничего, что говорит, что реализация фактически должна позвонить AlloCator.construct, и фактически много (например, GCC).

Стандарт C ++ 0x добавляет новые функции участника в интерфейс контейнера для подвижных типов и уточняет, как такие вещи, как оператор = ведут себя в их присутствии.

Смотрите www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2486.pdf.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top