Since the C++11 standard, the concurrency support library in Modern C++ is designed to solve problems in multi-thread operations and is updated in every new standard. This library includes built-in support for threads (std::thread
) with atomic operations (std::atomic
). In this post, we explain atomic logic operations that can be used with std::atomic
types.
Table of Contents
What is atomic (std::atomic) in C++?
C++11 adds atomic types and operations to the standard. Atomic types and operations provide a way of writing multi-threaded applications without using locks. In modern C++, the std::atomic<>
template class is defined in the <atomic>
header and it can be used to wrap other types to do atomic operations on that type. When a thread writes to an atomic object another thread can read from it. Every instantiation and full specialization of the std::atomic
template defines an atomic type.
Atomic types ensure any read or write operation synchronizes as part of multi-thread operations, (i.e. using these types in std::thread
). They work well on any type that is trivially copyable types which means it has at least one eligible copy constructor, move constructor, copy assignment operator, or move assignment operator and has non-deleted trivial destructor.
Here is a simple syntax for the atomic declaration:
1 2 3 |
atomic< type > type_name; |
Here is a simple std::atomic
example:
1 2 3 4 5 6 7 8 |
std::atomic<unsigned int> counter(0); // atomic type void myf() // a function to be used in multi-thread operations { counter++; // atomic operation } |
Atomic operations are operations on the of values atomic types (std::atomic
objects) in the atomic library that allows lockless concurrent programming. These operations are good in data races and these objects are free of data races. Different atomic operations can be done on the same atomic object in their sync. std::atomic
has many features to be used in atomic operations, Let’s see some of these addition and subtract operations now.
What are atomic logic operations in modern C++?
Atomic types can be used in logical operations as in standard C++ types, for example we can use fetch_and
, fetch_or
and fetch_xor
in atomic operations. These logic operators atomically replaces the value pointed by the given object with the result of bitwise AND/OR/XOR between the old value of object and argument. Note that these templates returns the previous value of that object.
Here is an example that uses fetch_and
, fetch_or
and fetch_xor
atomic operations,
1 2 3 4 5 6 7 8 9 10 11 12 |
std::atomic<char> a = true, b = true, c = true; std::atomic<char> pa = false, pb = false, pc = false; // previous a b c void myf() // a function to be used in multi-thread operations { pa = a.fetch_and( false ); // true AND false = false a = 0, pa = true pb = b.fetch_or( false ); // true OR false = true b = 1, pb = true pc = c.fetch_xor( true ); // true XOR true = false c = 0, pc = true } |
Here a, b, c values are changed to 0, 1 and 0 while pa pb pc goes to previous values of them. Note that here we use atomic char for boolean.
What are atomic logic operations in C++?
As same as above can use std::atomic_fetch_and
,
and std::atomic_
fetch_or
as below,std::atomic_
fetch_xor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
std::atomic<char> a = true, b = true, c = true; void myf2() { void myf2() { pa = std::atomic_fetch_and(&a, false) if( a ) { std::cout << "Compared with AND" << std::endl; } pb = std::atomic_fetch_or(&b, true); if( b ) { std::cout << "Compared with OR" << std::endl; } pc = std::atomic_fetch_xor(&c, true); if( c ) { std::cout << "Compared with XOR" << std::endl; } } } |
Is there a full example to atomic logic operations in C++?
Here is a full example to atomic logic operations in modern C++.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
#include <iostream> #include <vector> #include <atomic> #include <thread> #include <iomanip> std::atomic<char> a = true, b = true, c = true; std::atomic<char> pa = false, pb = false, pc = false; // previous a b c void myf() // a function to be used in multi-thread operations { pa = a.fetch_and( false ); // true AND false = false a = 0, pa = true pb = b.fetch_or( false ); // true OR false = true b = 1, pb = true pc = c.fetch_xor( true ); // true XOR true = false c = 0, pc = true } void myf2() { pa = std::atomic_fetch_and(&a, false) if( a ) { std::cout << "Compared with AND" << std::endl; } pb = std::atomic_fetch_or(&b, true); if( b ) { std::cout << "Compared with OR" << std::endl; } pc = std::atomic_fetch_xor(&c, true); if( c ) { std::cout << "Compared with XOR" << std::endl; } } int main() { std::vector< std::thread> myt; // vector for threads std::cout << "a:" << (int)a << " b:" << (int)b << " c:" << (int)c << std::endl; std::cout << "pa:" << (int)pa << " pb:" << (int)pb << " pc:" << (int)pc << std::endl << std::endl; myt.push_back( std::thread( myf ) ); for (auto& t : myt) { t.join(); // wait each thread execution done and join back } std::cout << "a:" << (int)a << " b:" << (int)b << " c:" << (int)c << std::endl; std::cout << "pa:" << (int)pa << " pb:" << (int)pb << " pc:" << (int)pc << std::endl; std::thread myt2 (myf2); myt2.join(); system("pause"); return 0; } |
Note that, every operation on these atomic types are called as atomic operation, there are add and sub operators too. For more information on this feature, see Atomic operations Proposal document.
C++ Builder is the easiest and fastest C and C++ IDE for building simple or professional applications on the Windows, MacOS, iOS & Android operating systems. It is also easy for beginners to learn with its wide range of samples, tutorials, help files, and LSP support for code. RAD Studio’s C++ Builder version comes with the award-winning VCL framework for high-performance native Windows apps and the powerful FireMonkey (FMX) framework for cross-platform UIs.
There is a free C++ Builder Community Edition for students, beginners, and startups; it can be downloaded from here. For professional developers, there are Professional, Architect, or Enterprise version.