I am updating an atomic variable size_t using from one thread and reading it from another. Following is the code:
Code:
// MyClass.hpp
#pragma once
#include <atomic>
class MyClass {
public:
size_t GetVal() {
return m_atomic_val;
}
void SetVal(const std::size_t val) {
m_atomic_val = val;
}
private:
std::atomic<size_t> m_atomic_val{0};
};
// main.cpp
#include "MyClass.hpp"
#include <iostream>
#include <thread>
int main() {
MyClass obj;
obj.SetVal(4);
std::thread my_thread = std::thread([&obj]{
std::cout << "Thread started" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(30));
obj.SetVal(8);
});
std::this_thread::sleep_for(std::chrono::seconds(2));
auto val = obj.GetVal();
std::cout << "The value is: " << val << std::endl;
my_thread.join();
}
Question:
But as you can see, I am updating m_atomic_val
which is a std::atomic<size_t>
with a size_t
which is non atomic. Will this have bad repercussions? Is this illegal?
The return type of GetVal
is size_t
but its returning a std::atomic<size_t>
. Is this wrong?
So, my primary quesion is that is mixing of atomic and non atomic variables allowed the way I am doing in the sample code?
This is only a simple example to demonstrate the question I have. What if there was one writer thread and one reader thread which are running concurrently and race conditions are very likely? Should I switch to using mutexes instead of atomics?
Environment:
My code runs on iOS, Android and macOS.
Assignment to an atomic object will accept any value of the correct type.
Since you have an std::atomic<size_t>
then any value or variable that is (or can be implicitly converted to) a size_t
can be used on the right-hand side of the assignment.
As for the GetVal
issue, std::atomic
have a conversion operator which will do the right thing, atomically fetch the value and give it to you for the return.
Another note regarding the GetVal
function: It will only be the fetching of the value that will be atomic, the return
of it will not be. So between the fetch and the actual return
the value of m_atomic_val
can change, but the old value will be returned.