I have a class that I want to use in different threads and I think I may be able to use std::atomic
this way:
class A
{
int x;
public:
A()
{
x=0;
}
void Add()
{
x++;
}
void Sub()
{
x--;
}
};
and in my code:
std::atomic<A> a;
and in a different thread:
a.Add();
and
a.Sub();
but I am getting an error that a.Add()
is not known. How can I solve this?
Is there any better way to do this?
Please note that it is an example, and what I want is to make sure that access to class A is thread-safe, so I can not use
std::atomic<int> x;
How can I make a class thread-safe using std::atomic
?
You need to make the x
attribute atomic, and not your whole class, as followed:
class A
{
std::atomic<int> x;
public:
A() {
x=0;
}
void Add() {
x++;
}
void Sub() {
x--;
}
};
The error you get in you original code is completely normal: there is no std::atomic<A>::Add
method (see here) unless you provide a specialization for std::atomic<A>
.
Referring your edit: you cannot magically make your class A
thread safe by using it as template argument of std::atomic
. To make it thread safe, you can make its attributes atomic (as suggested above and provided the standard library gives a specialization for it), or use mutexes to lock your ressources yourself. See the mutex header. For example:
class A
{
std::atomic<int> x;
std::vector<int> v;
std::mutex mtx;
void Add() {
x++;
}
void Sub() {
x--;
}
/* Example method to protect a vector */
void complexMethod() {
mtx.lock();
// Do whatever complex operation you need here
// - access element
// - erase element
// - etc ...
mtx.unlock();
}
/*
** Another example using std::lock_guard, as suggested in comments
** if you don't need to manually manipulate the mutex
*/
void complexMethod2() {
std::lock_guard<std::mutex> guard(mtx);
// access, erase, add elements ...
}
};