I'm implementing a very light atomic wrapper as a learning exercise for primitive data types in C++ for Windows, and I have a few simple questions about implementing the assignment operator. Consider the two implementations below:
// Simple assignment
Atomic& Atomic::operator=(const Atomic& other)
{
mValue = other.mValue;
return *this;
}
// Interlocked assignment
Atomic& Atomic::operator=(const Atomic& other)
{
_InterlockedExchange(&mValue, other.mValue);
return *this;
}
Assume that mValue is the correct type and that the Atomic class has it as a member.
_InterlockedExchange needed for a thread-safe assignment operator, or is the simple implementation enough to guarantee thread-safety?_InterlockedExchange required to guarantee thread safety on other platforms?if mValue is a primitive type (and at most 32 bits wide on a 32-bit CPU, at most 64 bits wide on a 64-bit CPU), and you're running on an x86 CPU (in 32 or 64 bit mode) and you don't manually misalign data, then memory reads/writes are guaranteed to be atomic.
This does not, in itself, mean that the compiler won't reorder memory accesses or even optimize it out entirely, but the CPU does guarantee that any well-aligned read/write with data of those sizes will be atomic.
However, note that I'm talking about atomicity, not thread safety, because "thread safety" depends on the context in which the code is used.
There are three issues that C++ atomic types deal with. First, a thread switch might occur in the middle of a read or write, resulting in garbled data; this is known as "tearing". Second, each processor has its own data cache, and writing a value in one thread doesn't necessarily update the value in another processor's cache; this is "stale data". Third, the compiler can reorder instructions to improve efficiency if the results don't violate various rules; if you don't tell it that data is shared between threads it may do things that surprise you.
Using std::atomic (or the various implementation-specific mechanisms for ensuring atomicity) handles all three problems. There's no good reason to bypass them; the library and compiler writers almost certainly know better than you do how to generate efficient code that works correctly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With