0

Whereas using a pointer argument instead of a reference has different behavior in a multi-threaded scenario. It that the value does change in the middle of the function call when altered in a separate thread. I'm looking for an explanation as to why the behavior is different between a pass-by-reference and a pass-by-pointer.

Some pseudo-code below. Change the argument type of value inside PrintValue to a pointer and the second EXPECT_EQ test will fail, due to the value actually being changed while waiting for the notification.

void PrintValue(int& value, ConditionVariable* condVar) {
  EXPECT_EQ(value, 5);
  condVar->WaitFor(std::chrono::milliseconds(100));
  EXPECT_EQ(value, 5); // will pass unless value is passed as pointer
}

TEST(MyTest, MyTestOnReference) {
  int a = 5;
  int* ptr_a = &a;
  ConditionVariable condVar;
  std::thread t(std::bind(&PrintValue, a, &condVar));
  milliSleep(25);
  *ptr_a = 50000; // change value of a while PrintValue is waiting for notification.
  condVar.Notify();
  t.join();
}
Anton Savelyev
  • 762
  • 7
  • 22

1 Answers1

1

std::bind will copy anything being passed as references. You need to use std::reference_wrapper and/or std::ref, e.g.:

  std::thread t(std::bind(&PrintValue, std::ref(a), &condVar));
Human-Compiler
  • 11,022
  • 1
  • 32
  • 59
  • Correct! Thanks. I actually missed the bind being used here. Relevant SO page on this: https://stackoverflow.com/a/26188213 – Anton Savelyev Oct 22 '20 at 18:01