Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use std::atomic<>

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 ?

like image 322
mans Avatar asked Jun 10 '15 15:06

mans


People also ask

What is std :: atomic used for?

std::atomic is specialized for all integral types to provide member functions specific to integral (like operators ++, --, fetch_add, fetch_sub, ...).

How do you declare an atomic variable in C++?

In order to solve this problem, C++ offers atomic variables that are thread-safe. The atomic type is implemented using mutex locks. If one thread acquires the mutex lock, then no other thread can acquire it until it is released by that particular thread.

What is atomic operation C++?

(C++11) [edit] The atomic library provides components for fine-grained atomic operations allowing for lockless concurrent programming. Each atomic operation is indivisible with regards to any other atomic operation that involves the same object. Atomic objects are free of data races.


1 Answers

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 ...   }  }; 
like image 179
Unda Avatar answered Sep 19 '22 14:09

Unda