Нужен ли здесь барьер памяти? * PEnd_ = v; __sync_synchronize (); ++ PEND _; & Quot ;?

pEnd_ является членом объекта и может увеличиваться только в add (), как показано ниже в одном потоке, он может быть прочитан другим потоком. Нужно ли __sync_synchronize в add ()?

struct Vector {
...
void add(int v) {
*pEnd_ = v;
__sync_synchronize(); // is this needed?
++pEnd_;
}
private:
int* pBegin_;
int* pEnd_;
}

итерации в другой теме.

for (p = pBegin_; p != pEnd_; ++p) {
// read barrier here may be inserted
if (*p) {
....
}
}

1

Решение

Без, по крайней мере, барьера памяти релиза, модификации, которую вы сделали для *pEnd не обязательно виден другим темам. Так что что-то нужно.

Строго говоря, нет, __sync_synchronize() не нужен, так как это полный барьер памяти. Если ваш компилятор не имеет встроенного барьера только для релиза (он же «барьер записи»), полный барьер является разумным.

На первый взгляд, существует гонка данных, вызванная тем, что ваш прирост pEnd не секвенируется по отношению к чтению из других потоков. Определенные платформы могут давать гарантии о int* доступ является атомарным и может также дать гарантии о том, что изменения становятся видимыми в других потоках в том же порядке, в котором они были записаны в этом потоке. Так что на некоторых платформах код в порядке (а полный барьер препятствует переупорядочению записей). Ничто из этого не является стандартным C ++, и он должен быть специфичным для аппаратного обеспечения, а не для компилятора.

3

Другие решения

Других решений пока нет …