4 ms·
> The code expects that a different thread writes to the variable at the same time that this thread might read from it - that's the definition of a race conditi
by jnordwick 7y ago
> The code expects that a different thread writes to the variable at the same time that this thread might read from it - that's the definition of a race condition,
No, that isn't. In one thread it reads a value over and over. Another thread will periodically set it. This isn't a race condition and requires no synchonization. On writer thread only, and you're fine. If the code was doing more, I didn't see it.
I just wrong something very similar yesterday where I had a counter that is read over and over and an async handler updated it. I had to make it volatile to prevent the the spin on it from optimizing out the load.
Yes, in low level programming, you have to know about the hardware, what a register is, what cache it, etc. C++ has a very lose (almost nonexistent) abstract model. This isn't UB.
> int is not the "correct type" because no int object lives at the pointed-to location after the cast
The string had its length prepended to it. There was an int there. Also, those aliasing rules are more about optimization issues, not as much about alignment issues (eg, if you are only writing for intel/amd hardware alignment only really matter for SIMD, and there is no penalty on unaligned access (with a few small exceptions that didn't apply here).
- MauranKilom 7y ago> No, that isn't. In one thread it reads a value over and over. Another thread will periodically set it. This isn't a race condition and requires no synch[r]onization. On[e] writer thread only, and you're fine. Sorry, wrong term by me. I meant data race, not race condition (although many would regard the former as a form of the latter). A data race is two or more threads accessing the same location without synchronization, where at least one of them is modifying the value. A data race results in undefined behavior. Here are the relevant sections from the C++ (draft) standard: http://eel.is/c++draft/intro.multithread#intro.races-21 http://eel.is/c++draft/intro.multithread#intro.races-21 http://eel.is/c++draft/intro.multithread#intro.races-2 http://eel.is/c++draft/intro.multithread#intro.races-2 > I just wro[te] something very similar yesterday where I had a counter that is read over and over and an async handler updated it. If you wrote this code in C++, you created a data race and your program has undefined behavior. > I had to make it volatile to prevent the the spin on it from optimizing out the load. volatile may prevent the load from being optimized out, but it does not prevent the data race (because it does not prevent instruction reordering). Your program still has undefined behavior. Further reading: https://www.kernel.org/doc/html/latest/process/volatile-considered-harmful.html https://www.kernel.org/doc/html/latest/process/volatile-cons... > C++ has a very lose (almost nonexistent) abstract model I don't know what you mean with "lo[o]se" or "almost nonexistent" but here are a few specifications of the abstract machine that C++ is defined on: http://eel.is/c++draft/basic.memobj http://eel.is/c++draft/basic.memobj http://eel.is/c++draft/basic.exec http://eel.is/c++draft/basic.exec > There was an int there. No. Just because you operate on the memory as if it was an int doesn't create an int there. > Also, those aliasing rules are more about optimization issues Correct! And those optimization issues are the primary way in which UB manifests itself in your program.
- dclusin 7y agoYou can leverage the cpu's atomic operations such as compare and set, compare and swap, as well as the properties of the memory subsystem to achieve thread safety without an operating system mediating the interaction. Here's a blog post from some people that have street cred to give you some idea of the potential performance benefits: https://mechanical-sympathy.blogspot.com/2013/08/lock-based-vs-lock-free-concurrent.html https://mechanical-sympathy.blogspot.com/2013/08/lock-based-...
- jnordwick 7y agoIt seems like you're one of the UB brigade that demands rigid adherence to the standard because some 8-bit microprocessor might not be able to read a 32-bit value atomically. Nobody care about that, and when writing high performance code, you write the hardware you target and care about. Reading and writing to the same int in memory is atomic for every hardware platform I care about. Even alignment issues don't matter for anything this is going to be run on. > No. Just because you operate on the memory as if it was an int doesn't create an int there. Don't be dumb. They wrote an int to the beginning of the buffer and then had to cast back to it, like every piece of networking or file code that had to save a binary number.