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.