пользовательский распределитель, использующий перемещение для вектора потока - PullRequest
2 голосов
/ 27 сентября 2010

В настоящее время я изучаю параллелизм в 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 только в этом контексте. Однако, пожалуйста, укажите мне на любые библиотеки, в которых это может быть реализовано, чтобы я мог покопаться в источнике.

Ответы [ 3 ]

2 голосов
/ 27 сентября 2010

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

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

2 голосов
/ 27 сентября 2010

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

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

0 голосов
/ 27 сентября 2010

Требование, чтобы контейнеры 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());

может привести к тому, что a выделит новое пространство, и под капотом будут скопированы копии, сделанные в новом базовом хранилище из старого.

Кроме того, в стандарте C ++ 03 нет ничего, что говорило бы, что реализация на самом деле должна вызывать allocator.construct, а на самом деле многие (например, gcc) этого не делают.

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

См. Www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2486.pdf

.
...