std::atomic<T>
provides synchronization for the operations that are defined in the atomic
template. That includes storing a value of type T
, getting the value of type T
, swapping a value of type T
with the T
in the atomic object, and a handful of compare and exchange operations. It is not a replacement for proper synchronization of operations on the contained object. In particular, calling LogMessage
from multiple threads will produce a data race if LogMessage
doesn't protect its data with a mutex.
Correct usage of std::atomic
-
18-09-2022 - |
Domanda
Is this the correct way to use std::atomic? I have a single Logger
declared at namespace level called LOGGER
:
class Logger {
public:
Logger();
~Logger();
bool Init(std::wstring logFileLocation);
bool Shutdown();
void const LogMessage(std::wstring message);
};
std::atomic<Logger&> LOGGER;
My expectation is that LOGGER
will instantiated once (no races; it will be initialized from a single known point in the code), but then accessed from multiple threads.
I'm new to multi-threading and thread safety in C++; but in C# or Java I would like to either make LOGGER
volatile or (in C#) put memory fences around it. Is this the correct analogue in C++?
Soluzione
Altri suggerimenti
The std::atomic
works on a "bag of bits": an object of type T
whose bitwise representation, stored in sizeof(T)
bytes, carries the whole value. It means that nothing that needs to atomically manipulated (by these specific operations on std::atomic<T>
) can reside in an object pointed to by a member of T
, that would never work.
Also it means that std::atomic<T>
can only work for a concrete object type T
. A reference type is an "alias" for another object: a reference is not an object.