{"id":4795,"date":"2016-06-22T05:44:36","date_gmt":"2016-06-22T05:44:36","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/atomics\/"},"modified":"2023-06-26T12:52:18","modified_gmt":"2023-06-26T12:52:18","slug":"atomics","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/atomics\/","title":{"rendered":"Atomics"},"content":{"rendered":"<p>In addition to booleans, there is atomics for pointers, integrals, and user-defined types. The rules for user-defined types are special.<span style=\"font-family: courier new,courier;\"><\/span><\/p>\n<p><!--more--><\/p>\n<p>Both. The atomic wrapper on a pointer <span style=\"font-family: courier new,courier;\">T* std::atomic&lt;T*&gt; <\/span>or on an integral type <span style=\"font-family: courier new,courier;\">integ std::atomic&lt;integ&gt;<\/span> enables the CAS (compare-and-swap) operations.<\/p>\n<h2><span style=\"font-family: courier new,courier;\">std::atomic&lt;T*&gt;<\/span><\/h2>\n<p>The atomic pointer <span style=\"font-family: courier new,courier;\">std::atomic&lt;T*&gt;<\/span> behaves like a plain pointer <span style=\"font-family: courier new,courier;\">T*<\/span>. So<span style=\"font-family: courier new,courier;\"> std::atomic&lt;T*&gt;<\/span> supports pointer arithmetic and pre-and post-increment or pre-and post-decrement operations. Have a look at the short example.<\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #2b91af;\">int<\/span> intArray[5];\r\nstd::atomic&lt;<span style=\"color: #2b91af;\">int<\/span>*&gt; p(intArray);\r\np++;\r\nassert(p.load() == &amp;intArray[1]);\r\np+=1;\r\nassert(p.load() == &amp;intArray[2]);\r\n--p;\r\nassert(p.load() == &amp;intArray[1]);\r\n<\/pre>\n<\/div>\n<h2><span style=\"font-family: courier new,courier;\">std::atomic&lt;integral type&gt;<\/span><\/h2>\n<p>In C++11, there are atomic types to the known integral data types. As ever, you can read the whole stuff about atomic integral data types &#8211; including their operations &#8211; on the page <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/atomic\/atomic\">en.cppreference.com. <\/a>A <span style=\"font-family: courier new,courier;\">std::atomic&lt;integral type&gt;<\/span> allows all that a <span style=\"font-family: courier new,courier;\">std::atomic_flag<\/span> or a <span style=\"font-family: courier new,courier;\">std::atomic&lt;bool&gt;<\/span> is capable of, but even more.<\/p>\n<p>The composite assignment operators <span style=\"font-family: courier new,courier;\">+=, -=, &amp;=, |=<\/span> and<span style=\"font-family: courier new,courier;\"> ^=<\/span> and there pedants <span style=\"font-family: courier new,courier;\">std::atomic&lt;&gt;::fetch_add(), std::atomic&lt;&gt;::fetch_sub(), std::atomic&lt;&gt;::fetch_and(), std::atomic&lt;&gt;::fetch_or()<\/span> and <span style=\"font-family: courier new,courier;\">std::atomic&lt;&gt;::fetch_xor()<\/span> are the most interesting ones. There is a little difference in the atomic read and write operations. The composite assignment operators return the new value, and the fetch variations the old value. A deeper look gives more insight. There is no multiplication, division, and shift operation in an atomic way. But that is not that big a restriction because these operations are relatively seldom needed and can easily be implemented. How? Look at the example.<span><\/span><\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"> 1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\n 7\r\n 8\r\n 9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ fetch_mult.cpp<\/span>\r\n\r\n<span style=\"color: #0000ff;\">#include &lt;atomic&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;iostream&gt;<\/span>\r\n\r\n<span style=\"color: #0000ff;\">template<\/span> &lt;<span style=\"color: #0000ff;\">typename<\/span> T&gt;\r\nT fetch_mult(std::atomic&lt;T&gt;&amp; shared, T mult){\r\n  T oldValue= shared.load();\r\n  <span style=\"color: #0000ff;\">while<\/span> (!shared.compare_exchange_strong(oldValue, oldValue * mult));\r\n  <span style=\"color: #0000ff;\">return<\/span> oldValue;\r\n}\r\n\r\n<span style=\"color: #2b91af;\">int<\/span> main(){\r\n  std::atomic&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; myInt{5};\r\n  std::cout &lt;&lt; myInt &lt;&lt; std::endl;          \r\n  fetch_mult(myInt,5);\r\n  std::cout &lt;&lt; myInt &lt;&lt; std::endl;         \r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>I should mention one point. The addition in line 9 will only happen if the relation <span style=\"font-family: courier new,courier;\">oldValue == shared<\/span> holds. So to be sure that the multiplication will always take place, I put the multiplication in a <span style=\"font-family: courier new,courier;\">while<\/span> loop. The result of the program is not so thrilling.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-4792\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/06\/fetch_mult.PNG\" alt=\"fetch mult\" width=\"500\" height=\"84\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/06\/fetch_mult.PNG 1148w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/06\/fetch_mult-300x50.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/06\/fetch_mult-1024x171.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/06\/fetch_mult-768x128.png 768w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/p>\n<p>The implementation of the function template <span style=\"font-family: courier new,courier;\">fetch_mult<\/span> is generic, too generic. So you can use it with an arbitrary type. In case I use instead of the number 5 the C-String 5, the Microsoft compiler complains that the call is ambiguous.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-4793\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/06\/fetch_mult_error.PNG\" alt=\"fetch mult error\" width=\"500\" height=\"157\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/06\/fetch_mult_error.PNG 1148w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/06\/fetch_mult_error-300x94.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/06\/fetch_mult_error-1024x321.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/06\/fetch_mult_error-768x241.png 768w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/p>\n<p>&#8220;5&#8221; can be interpreted as a <span style=\"font-family: courier new,courier;\">const char*<\/span> or an <span style=\"font-family: courier new,courier;\">int.<\/span> That was not my intention.<span style=\"font-family: courier new,courier;\"> <\/span><span style=\"font-family: courier new,courier;\"><\/span>The template argument should be an integral type. The correct use case for concepts lite. With concepts lite, you can express constraints to the template parameter. Sad to say, but they will not be part of C++17. We should hope for the C++20 standard.<\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\">1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0000ff;\">template<\/span> &lt;<span style=\"color: #0000ff;\">typename<\/span> T&gt;\r\n  requires std::is_integral&lt;T&gt;::value\r\nT fetch_mult(std::atomic&lt;T&gt;&amp; shared, T mult){\r\n  T oldValue= shared.load();\r\n  <span style=\"color: #0000ff;\">while<\/span> (!shared.compare_exchange_strong(oldValue, oldValue * mult));\r\n  <span style=\"color: #0000ff;\">return<\/span> oldValue;\r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The predicate <span style=\"font-family: courier new,courier;\">std::is_integral&lt;T&gt;::value<\/span> will be evaluated by the compiler. If T is not an integral type, the compiler will complain. <span style=\"font-family: courier new,courier;\">std::is_integral<\/span> is a function of the new <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/header\/type_traits\">type-traits library<\/a>, part of&nbsp;C++11. The required condition in line 2 defines the constraints on the template parameter. The compiler checks the contract at compile time.<\/p>\n<p>You can define your atomic types.<\/p>\n<\/p>\n<h2>std::atomic&lt;user defined type&gt;<\/h2>\n<p>There are a lot of severe restrictions on a user-defined type to get an atomic type <span style=\"font-family: courier new,courier;\">std::atomic&lt;MyType&gt;<\/span>. These restrictions are on the type but on the available operations that <span style=\"font-family: courier new,courier;\">std::atomic&lt;MyType&gt;<\/span> can perform.<\/p>\n<p>For MyType, there are the following restrictions:<\/p>\n<ul>\n<li>The copy assignment operator for <span style=\"font-family: courier new,courier;\">MyType must be trivial for all base classes of MyType and all non-static members of MyType<\/span>. Only an automatic by the compiler-generated copy assignment operator is trivial. To say it the other way around. User-defined copy assignment operators are not trivial.<\/li>\n<li><span style=\"font-family: courier new,courier;\">MyType<\/span> must not have virtual methods or base classes.<\/li>\n<li><span style=\"font-family: courier new,courier;\">MyType<\/span> must be bitwise comparable so that the C functions <span style=\"font-family: courier new,courier;\">memcpy<\/span> or <span style=\"font-family: courier new,courier;\">memcmp<\/span> can be applied.<\/li>\n<\/ul>\n<p>You can check the constraints&nbsp;on <span style=\"font-family: courier new,courier;\">MyType<\/span> with the functions <span style=\"font-family: courier new,courier;\">std::is_trivially_copy_constructible,<\/span> <span style=\"font-family: courier new,courier;\">std::is_polymorphic<\/span>, and <span style=\"font-family: courier new,courier;\">std::is_trivial<\/span> at compile time. All the functions are part of the <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/header\/type_traits\">type-traits library.<\/a><\/p>\n<p>Only a reduced set of operations is supported for the user-defined type, std::atomic&lt;MyType&gt;.<\/p>\n<h2>Atomic operations<\/h2>\n<p>To get the great picture, I displayed the atomic operations dependent on the atomic type in the following table.<\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-4794\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/06\/atomicOperationsEng.png\" alt=\"atomicOperationsEng\" width=\"700\" height=\"453\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/06\/atomicOperationsEng.png 928w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/06\/atomicOperationsEng-300x194.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/06\/atomicOperationsEng-768x497.png 768w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/p>\n<h2>Free atomic functions and smart pointers<span style=\"font-family: arial,helvetica,sans-serif;\"> <\/span><span style=\"font-family: courier new,courier;\"><span style=\"font-family: arial,helvetica,sans-serif;\"><br \/><\/span><\/span><\/h2>\n<p>The functionality of the class templates <span style=\"font-family: courier new,courier;\">std::atomic<\/span> and the Flag <span style=\"font-family: courier new,courier;\">std::atomic_flag<\/span> can be used as a <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/atomic\">free function<\/a>. Because the free functions use atomic pointers instead of references, they are compatible with C. The atomic free functions support the same types as the class template <span style=\"font-family: courier new,courier;\">std::atomic<\/span> but in addition to that the smart pointer <span style=\"font-family: courier new,courier;\">std::shared_ptr.<\/span> That is special because <span style=\"font-family: courier new,courier;\">std::shared_ptr<\/span> is not an atomic data type. The C++ committee recognized the necessity that instances of smart pointers that maintain the reference counters and objects under their hood must be modifiable in an atomic way.<\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<pre style=\"margin: 0; line-height: 125%;\">std::shared_ptr&lt;MyData&gt; p;\r\nstd::shared_ptr&lt;MyData&gt; p2= std::atomic_load(&amp;p);\r\nstd::shared_ptr&lt;MyData&gt; p3(<span style=\"color: #0000ff;\">new<\/span> MyData);\r\nstd::atomic_store(&amp;p, p3);<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>To be clear.<strong> The atomic characteristic will only hold for the reference counter but not the object.<\/strong> That was the reason we get a <span style=\"font-family: courier new,courier;\">std::atomic_shared_ptr <\/span>in the future (I&#8217;m not sure if the future is called C++17 or C++20.&nbsp;I was often wrong in the past.), which is based on a <span style=\"font-family: courier new,courier;\">std::shared_ptr<\/span> and guarantees the atomicity of the underlying object. That will also hold for <span style=\"font-family: courier new,courier;\">std::weak_ptr<\/span>. s<span style=\"font-family: courier new,courier;\">td::weak_ptr<\/span>, which is a temporary resource owner, helps break the cyclic dependencies of <span style=\"font-family: courier new,courier;\">std::shared_ptr.<\/span> The name of the new atomic <span style=\"font-family: courier new,courier;\">std::weak_ptr<\/span> will be <span style=\"font-family: courier new,courier;\">std::atomic_weak_ptr<\/span>. To complete the picture, the atomic version of<span style=\"font-family: arial,helvetica,sans-serif;\"> <span style=\"font-family: courier new,courier;\">std::unique_ptr<\/span> <\/span><span>is called<\/span><span style=\"font-family: arial,helvetica,sans-serif;\"> <span style=\"font-family: courier new,courier;\">std::atomic_unique_ptr.<\/span>&nbsp;<\/span><\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>Now the foundations of the atomic data types are laid. In the <a href=\"https:\/\/www.modernescpp.com\/index.php\/synchronization-and-ordering-constraints\">next post<\/a>, I will write about the synchronization and ordering constraints on atomics.<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In addition to booleans, there is atomics for pointers, integrals, and user-defined types. The rules for user-defined types are special.<\/p>\n","protected":false},"author":21,"featured_media":4792,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[368],"tags":[434,519],"class_list":["post-4795","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-multithreading-memory-model","tag-atomics","tag-sequential-consistency"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/4795","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=4795"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/4795\/revisions"}],"predecessor-version":[{"id":6969,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/4795\/revisions\/6969"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/4792"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=4795"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=4795"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=4795"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}