What does “happens before” mean in the C++11 spec?

柔情痞子 提交于 2019-12-11 10:09:06

问题


I'm trying to understand the meaning of happens before in the C++11 spec, and in particular whether the spec assumes any informal understanding of the term in addition to what is specified. I'm working from draft N3290.

A straight-forward argument that the term should be interpreted only with respect to the specification itself is that the spec actually talks about its own definition of the term. For example, 1.10.6: "happens before (as defined below)" or 1.10.11: "'happens before' relation, defined below."

On the other hand, 1.10.12 reads "An evaluation A happens before an evaluation B if: ..." If this were a definition of happens before, I would expect it to read "if and only if." So it appears the spec is defining some minimum requirements of the happens before relation, yet leaving it open to other factors, which might include some informal notion of what the term means, or might include language in other parts of the spec.

Paragraph 1.10.13 then defines visible side effect, or does it? It looks like a definition because visible side effect is in italics, but the definition is in terms of happens before, so should this alternatively be read as a further restriction on happens before given the intuitive notion of visible side effect? In other words, if B sees A, does this imply that A happened before B (a further restriction on the definition of happens before), or is the implication intended only in the other direction, namely that when A happens before B, then A must be a visible side effect.

Here is a specific example (inspired by this question, but here I'm just trying to understand happens before, and with respect to C++ rather than C, since the C++ spec seems a little clearer):

#include <atomic>
#include <cassert>
#include <thread>

using namespace std;

atomic<int> a;
atomic<int> b;

void
p1()
{
  atomic_store_explicit(&a, 1, memory_order_relaxed);       // 1
}

void
p2()
{
  if (atomic_load_explicit(&a, memory_order_relaxed)) {
    //atomic_thread_fence(memory_order_release);
    atomic_store_explicit(&b, 1, memory_order_relaxed);     // 2
  }
}

void
p3()
{
  int local = 1;
  if (atomic_load_explicit(&b, memory_order_relaxed)) {
    //atomic_thread_fence(memory_order_acquire);
    local = atomic_load_explicit(&a, memory_order_relaxed); // 3
  }
  assert (local == 1);
}

int
main()
{
  thread t1{p1}, t2{p2}, t3{p3};
  t1.join();
  t2.join();
  t3.join();
}

Given an execution in which the line marked // 3 executes, does the spec require that the line marked // 1 happen before any other line in the program? Informally, line // 1 is a visible side effect at line // 2, so does this mean // 1 happened before // 2, in which case an equivalent argument says // 2 happened before // 3 and the assertion cannot fail? For purely extrinsic reasons (namely an understanding of how NUMA works and an assumption that the language committee wanted to leave room for relaxed memory order optimizations), I think these happens before conditions probably do not hold and the assertion can fail.

My next question is whether uncommenting the fences in p2 and p3 has any effect on whether // 1 happens before any other statement? Here I suspect that unless there is already some happens before connection between // 1 and code in the other threads, uncommenting fences in other threads will not change this. (Though that would imply there is no way to prevent the assertion from failing using only fences.)

As a final note, I have this problem where the spec contains abstract language about A, B, M, X, Y that seems to imply one thing until I actually go and try to map A, B, etc., to statements and variables in my code, at which point it seems to imply something else. So I'm hoping for an answer that actually connects the C++ spec to the example code in what might seem like overly-pedantic detail. (E.g., just stating that // 1 happens before // 3 because of read-read coherence does not answer my question--my question is more about how the specific definition of read-read coherence in the C++11 spec applies to my specific code example, and about what basis there is for assuming the definition of read-read coherence governs the definition of happens before rather than vice versa.)

来源:https://stackoverflow.com/questions/34244647/what-does-happens-before-mean-in-the-c11-spec

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!