Is memory barrier needed here "*pEnd_ = v; __sync_synchronize (); ++pEnd_;"?

268 Views Asked by At

pEnd_ is an object member and can only increase in add() as below in one thread, it may be read by another thread. Do we need __sync_synchronize in add()?

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

iterate in another thread.

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

There are 1 best solutions below

0
On

Without at least a release memory barrier, the modification you made to *pEnd is not necessarily visible to other threads. So something is needed.

Strictly speaking no, __sync_synchronize() is not needed since it's a full memory barrier. If your compiler doesn't have an intrinsic for a release-only barrier (aka "write barrier"), the full barrier is reasonable.

On the face of it, there is a data race caused by the fact that your increment of pEnd is unsequenced with respect to reads from other threads. Particular platforms might make guarantees about int* access being atomic, and might also make guarantees about the changes becoming visible in other threads in the same order they were written in this thread. So on some platforms the code is OK (and the full barrier prevents the writes from being reordered). None of that is standard C++, and it's liable to be specific to the hardware rather than to the compiler.