4

This is sort of a follow-up to Could a C++ implementation, in theory, parallelise the evaluation of two function arguments?

Suppose I have the following C++11 program:

#include <cstdio>
using std::printf;
int g() { printf("1\n"); printf("3\n"); return 2; }
int h() { printf("2\n"); printf("4\n"); return 3; }
void f(int a, int b) { printf("%i\n", a+b); }
int main() { f(g(), h()); }

Certainly the following outputs are observable:

1 3 2 4 5
2 4 1 3 5

What about 1 2 3 4 5?

(As far as I can tell, the only constraints are that 1 is sequenced before 3, 2 is sequenced before 4, and both 3 and 4 are sequenced before 5.)

Community
  • 1
  • 1
tmyklebu
  • 13,915
  • 3
  • 28
  • 57
  • That's not a followup, it's a duplicate. `1 2 3 4` could only happen if an implementation was allowed to run the two functions concurrently. – Mat Nov 18 '12 at 19:42
  • 1
    @Mat you are misunderstanding this. An optimization as asked by tomalak is something different than producing two different outputs. – Johannes Schaub - litb Nov 18 '12 at 19:43
  • 1
    @JohannesSchaub-litb I think it's the same question. There is nothing in the other question to suggest that `f` and `g` have no observable effects, and the answers to that other question point out that distinction. –  Nov 18 '12 at 19:46
  • @hvd incorrect. Tomalak says "Such a parallelisation could only kick in were g and h known to be fairly trivial (in the most obvious case, accessing only data local to their bodies) so as not to introduce concurrency issues" – Johannes Schaub - litb Nov 18 '12 at 19:47
  • They're certainly related, but I'm asking about observable behaviour. What's curious is that, as far as I know, the expression f(g(i()), h(j())) can be evaluated as i, then j, then g, then h, then f. – tmyklebu Nov 18 '12 at 19:48
  • @JohannesSchaub-litb That's something different. There are no concurrency issues if `g` and `h` acquire a lock (I'm not sure how to do that in standard C++11, but I'm assuming it's possible) before the `printf` calls. –  Nov 18 '12 at 19:51
  • @hvd yes if they aquire a lock around the function bodies, then these functions can be executed "interleaved", because you cannot observe it. but as shown, these functions are not allowed to be executed interleavingly because of the concurrency issues mentioned by tomalak. A "concurrency issue" is not just a data race in my definition. It is any event that causes concurrent code to violate a specification. – Johannes Schaub - litb Nov 18 '12 at 19:57
  • I think it's not a duplicate but that the answer "no" to my question means the answer is to this question is also "no". – Lightness Races in Orbit Nov 18 '12 at 20:03
  • @JohannesSchaub-litb I meant acquire lock, print, release lock, acquire lock again, print, release lock again. The two functions would not necessarily have bugs if they were executed concurrently from separate threads (and printf is replaced with something else), that's what I mean by "there are no concurrency issues". I see what you mean now, you interpreted the other question different from how I did, and that's a legitimate interpretation. –  Nov 18 '12 at 20:08

1 Answers1

8

C++03 did normatively say that function invocations do not interleave. C++11 says normatively that

Every evaluation in the calling function (including other function calls) that is not otherwise specifically sequenced before or after the execution of the body of the called function is indeterminately sequenced with respect to the execution of the called function.

Both are sufficient to disallow this.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212