The synchronization concern is already covered in other answers (specifically David Schwartz's).
There's another concern I don't see addressed, though: this is usually a bad design.
Consider David's example code, assuming we have a correctly-synchronized version of foo
{
foo j;
some_func(j);
while (j.count() == 0)
{
// do we still expect (j.count() == 0) here?
bar();
}
}
The code suggests that the while
condition still holds in the body. That's how single-threaded code works, after all.
But of course, even if we correctly synchronize the implementation of a getter, the setter can still be called from another thread, between our while
condition succeeding and the first instruction of the loop body executing.
So, if any logic in the loop body can't depend on the condition being true, what was the point of testing it?
Sometimes it makes perfect sense, such as
while (foo.shouldKeepRunning())
{
// foo event loop or something
}
where it's OK if our shouldKeepRunning
state changes during the loop body, because we only need to test it periodically. However, if you're going to do something with count
, you need a longer-lived lock, and an interface to support it:
{
auto guard = j.lock_guard();
while (j.count(guard) == 0) // prove to count that we're locked
{
// now we _know_ count is zero in the body
// (but bar should release and re-acquire the lock or that can never change)
bar(j);
}
} // guard goes out of scope and unlocks