initialize std::thread

Started by
24 comments, last by frob 6 years, 2 months ago
4 hours ago, Bregma said:

Unless of course the compiler decides to reorder the instructions in your code, or the CPU is superscalar and performs out-of-order and/or speculative execution, and you end up using the results of your interlocked add before actually calling that instruction: a locked processor instruction does not affect that but a fence does.  Then again, you're using this in a multi-threaded application, so you're going to get pre-empted right after your InterlockAdd and the value gets changed by the other thread after you've obtained it, and you're left scratching your head why things don't work, sometimes, maybe.

 

 

Several things:

  • InterlockedAdd is a compiler intrinsic, for which the compiler is aware of the semantics. As such, the compiler should know not to reorder instructions around it. If you were to implement InterlockedAdd yourself, you are correct that it is possible to get it wrong, if you don't communicate the fencing semantics of an atomic instruction to the compiler. Note, these fencing semantics do not imply an actual fence instruction on every architecture.
  • I would recommend using C/C++ 11 atomics over compiler intrinsics such as these to avoid learning all the nuances of each compilers intrinsics, including InterlockedAdd.
  • As for the processor executing your instruction out of order, I disagree that fences are needed in x86. The proof is here, http://www.cl.cam.ac.uk/~pes20/cpp/popl085ap-sewell.pdf, though I don't claim to have read and understood all of it myself. I believe it shows that a locked instruction is sufficient on all atomic stores to guarantee sequential consistency.
  • You are right that locked instructions do not prevent a value from changing after you have read it, but this does not prevent you from being able to reason about your program having sequential consistency. Yes, you still need correct algorithms that don't assume that a shared value will necessarily still be of the value last read from it, unless otherwise guaranteed in code.

 

Advertisement
14 hours ago, King Mir said:

That's backwards. The entire point of using atomic operations is so the compiler adds those fences.

I meant in the opposite direction. If you are using a volatile variable in atomic intrinsics, the compiler may be smart enough to avoid applying the fences in all the non-atomic cases.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

1 hour ago, swiftcoder said:

I meant in the opposite direction. If you are using a volatile variable in atomic intrinsics, the compiler may be smart enough to avoid applying the fences in all the non-atomic cases.

So if I understand you, what you're saying is that this generates a fence on Visual Studio:


volitile LONG var = 0;
var += 10l;
	

However, you think this won't even though the first argument is volatile:


volatile LONG var = 0;
InterlockedAddNoFence(var, 10l);
	

If so, I think you're right.

On 05/02/2018 at 8:41 AM, Cat's machete said:

funniest thing is whenever i add ListenThread.join(); and create exit condition so thread actually quits it doesnt crash anything.

That's by design. std::thread::~thread is calling std::terminate(). So, either join() with the thread, or detach() it if you're 100% sure that's what you need.

Note that even though that isn't required, it is something that Microsoft has chosen to do beyond what the standard requires.

It is non-standard behavior, but they do it because too many programs have misused the old behavior in bug-inducing ways.  It adds a performance penalty so use with caution.

As I mentioned in my earlier posts, old code that correctly relied on the behavior in decades past would often use object aliases for both a volatile version and a non-volatile version. Tricky to get right and disastrous to get wrong, it can eliminate some of the performance issues.

Or, you can use tools recognized by the language and compiler for the correct behavior which is the better choice in modern code.

This topic is closed to new replies.

Advertisement