C ++ atomic list container

I play with std::atomic , but I think that I did not quite understand the concept. I wonder why there are no atomic containers. So I played a little. First I tried the following:

 std::atomic<std::list<int> > atomicList; 

But as some other people have already noted, this does not work, because the constructor is noexcept . So I created some kind of hack:

 template<class T> class MyList { public: //Make sure that no exception is thrown MyList() noexcept try: l() {}catch(...) {} void push_back(const T &t) { l.push_back(t); } void pop_front() { l.pop_front(); } size_t size() const { return l.size(); } private: list<T> l; }; atomic<MyList<int> > atomicList; 

Now I worked with it, but I found that it does not work correctly, and I get errors with segmentation errors.

Can someone explain why it is not possible to create an atomic list?

EDIT: If someone wants to see how my test program is really looking for a better understanding:

 #include <list> #include <thread> #include <sys/time.h> #include <iostream> #include <atomic> using namespace std; template<class T> class MyList { public: MyList() noexcept try: l() {}catch(...) {} void push_back(const T &t) { l.push_back(t); } void pop_front() { l.pop_front(); } size_t size() const { return l.size(); } private: list<T> l; }; atomic<MyList<int> > l; void work() { for(unsigned int i = 0; i < 100000; ++i) { //Called operator() ((MyList<int>&)l).push_back(i); ((MyList<int>&)l).push_back(((MyList<int>&)l).size()); ((MyList<int>&)l).pop_front(); } } int main(int argc, char *args[]) { struct timeval time1; struct timeval time2; gettimeofday(&time1, 0); thread t1(work); thread t2(work); thread t3(work); thread t4(work); t1.join(); t2.join(); t3.join(); t4.join(); gettimeofday(&time2, 0); cout<<((time2.tv_sec-time1.tv_sec)+double(time2.tv_usec-time1.tv_usec)/1000000)<<endl; } 
+5
source share
2 answers

The first and most important problem: this cannot work. You need synchronization around the performance of member functions, not to retrieve a list. std::atomic doesn't even start to resemble what you need.

As for your attempt at implementation, dropping atomic<T> to T& cannot do anything reasonable.

And even if it were significant, such a throw would completely forget about the atomicity of your object, and therefore everything that you do with links will not be atomic.

+4
source
 ((MyList<int>&)l).push_back(i); 

std::atomic does not provide a conversion operator for a reference. If you used static_cast , it would not even compile, but here C-cast will directly static_cast std::atomic<MyList<int>> as MyList<int> , which has good reasons not to work.

You cannot directly change that in std::atomic . You need to get a copy of the data using load() , change that copy, and then change it to store() .

+1
source

All Articles