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) {
....
}
}
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 aboutint*
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.