I am trying to implement a thread-safe STL vector without mutexes. So I went through the thismessage and implemented a shell for atomic primitives.
However, when I ran the code below, it displayed twice Failed!from the code below (only two instances of the race conditions), so it does not seem to be thread safe. I am wondering how can I fix this?
Wrapper class
template<typename T>
struct AtomicVariable
{
std::atomic<T> atomic;
AtomicVariable() : atomic(T()) {}
explicit AtomicVariable(T const& v) : atomic(v) {}
explicit AtomicVariable(std::atomic<T> const& a) : atomic(a.load()) {}
AtomicVariable(AtomicVariable const&other) :
atomic(other.atomic.load()) {}
inline AtomicVariable& operator=(AtomicVariable const &rhs) {
atomic.store(rhs.atomic.load());
return *this;
}
inline AtomicVariable& operator+=(AtomicVariable const &rhs) {
atomic.store(rhs.atomic.load() + atomic.load());
return *this;
}
inline bool operator!=(AtomicVariable const &rhs) {
return !(atomic.load() == rhs.atomic.load());
}
};
typedef AtomicVariable<int> AtomicInt;
Features and Testing
vector<AtomicInt> common(100, AtomicInt(0));
void add10(vector<AtomicInt> ¶m){
for (vector<AtomicInt>::iterator it = param.begin();
it != param.end(); ++it){
*it += AtomicInt(10);
}
}
void add100(vector<AtomicInt> ¶m){
for (vector<AtomicInt>::iterator it = param.begin();
it != param.end(); ++it){
*it += AtomicInt(100);
}
}
void doParallelProcessing(){
std::thread t1(add10, std::ref(common));
std::thread t2(add100, std::ref(common));
t1.join();
t2.join();
for (vector<AtomicInt>::iterator it = common.begin();
it != common.end(); ++it){
if (*it != AtomicInt(110)){
cout << "Failed!" << endl;
}
}
}
int main(int argc, char *argv[]) {
for (int i = 0; i < 100000; i++){
common.clear();
common.resize(100, AtomicInt(0));
doParallelProcessing();
}
}
Is there such a thing as an atomic container? I also checked this with the usual one vector<int>, it had no output Failed, but it might just be a coincidence.