{"id":6050,"date":"2020-12-08T19:56:33","date_gmt":"2020-12-08T19:56:33","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/atomic-ref\/"},"modified":"2023-06-26T09:36:07","modified_gmt":"2023-06-26T09:36:07","slug":"atomic-ref","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/atomic-ref\/","title":{"rendered":"Atomic References with C++20"},"content":{"rendered":"<p>Atomics receives a few essential extensions in C++20. Today, I start with the new data type<code> std::atomic_ref.<\/code><\/p>\n<p><!--more--><\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5945\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/07\/TimelineCpp20CoreLanguage.png\" alt=\"TimelineCpp20CoreLanguage\" width=\"650\" height=\"265\" style=\"display: block; margin-left: auto; margin-right: auto;\" \/><\/p>\n<p>The type<code>&nbsp;std::atomic_ref<\/code> applies atomic operations to its referenced object.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"std_atomic_ref\"><\/span><code>std::atomic_ref<\/code><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Concurrent writing and reading using a <code>std::atomic_ref<\/code> is no data race. The lifetime of the referenced object must exceed the lifetime of the <code>std::atomic_ref<\/code>. Accessing a subobject of the referenced object with a <code>std::atomic_ref<\/code> is not well-defined.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Motivation\"><\/span>Motivation<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>You may think using a reference inside an atomic would do the job. Unfortunately not.<\/p>\n<p>In the following program, I have a class <code>ExpensiveToCopy<\/code>, which includes a <code>counter<\/code>. The <code>counter<\/code> is concurrently incremented by a few threads. Consequently, <code>counter<\/code> has to be protected.<\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ atomicReference.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;atomic&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;random&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;thread&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;vector&gt;<\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> ExpensiveToCopy {\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> counter{};\r\n};\r\n \r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">getRandom<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> begin, <span style=\"color: #007788; font-weight: bold;\">int<\/span> end) {            <span style=\"color: #0099ff; font-style: italic;\">\/\/ (6)<\/span>\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>random_device seed;        <span style=\"color: #0099ff; font-style: italic;\">\/\/ initial seed<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>mt19937 engine(seed());    <span style=\"color: #0099ff; font-style: italic;\">\/\/ generator<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>uniform_int_distribution<span style=\"color: #555555;\">&lt;&gt;<\/span> uniformDist(begin, end);\r\n\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> uniformDist(engine);\r\n}\r\n \r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">count<\/span>(ExpensiveToCopy<span style=\"color: #555555;\">&amp;<\/span> exp) {                 <span style=\"color: #0099ff; font-style: italic;\">     \/\/ (2)<\/span>\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>vector<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span><span style=\"color: #555555;\">&gt;<\/span> v;\r\n    std<span style=\"color: #555555;\">::<\/span>atomic<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span> counter{exp.counter};              <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span>\r\n    \r\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #007788; font-weight: bold;\">int<\/span> n <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>; n <span style=\"color: #555555;\">&lt;<\/span> <span style=\"color: #ff6600;\">10<\/span>; <span style=\"color: #555555;\">++<\/span>n) {                      <span style=\"color: #0099ff; font-style: italic;\">\/\/ (4)<\/span>\r\n        v.emplace_back([<span style=\"color: #555555;\">&amp;<\/span>counter] {\r\n            <span style=\"color: #006699; font-weight: bold;\">auto<\/span> randomNumber <span style=\"color: #555555;\">=<\/span> getRandom(<span style=\"color: #ff6600;\">100<\/span>, <span style=\"color: #ff6600;\">200<\/span>);    <span style=\"color: #0099ff; font-style: italic;\">\/\/ (5)<\/span>\r\n            <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #007788; font-weight: bold;\">int<\/span> i <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>; i <span style=\"color: #555555;\">&lt;<\/span> randomNumber; <span style=\"color: #555555;\">++<\/span>i) { <span style=\"color: #555555;\">++<\/span>counter; }\r\n        });\r\n    }\r\n    \r\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #006699; font-weight: bold;\">auto<\/span><span style=\"color: #555555;\">&amp;<\/span> t <span style=\"color: #555555;\">:<\/span> v) t.join();\r\n\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n\r\n    ExpensiveToCopy exp;              <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\r\n    count(exp);\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"exp.counter: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> exp.counter <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    \r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p><code>exp<\/code> (1) is the expensive-to-copy object. For performance reasons, the function <code>count<\/code> (2) takes <code>exp<\/code> by reference. <code>count<\/code> initializes the <code>std::atomic&lt;int&gt;<\/code> with <code>exp.counter (<\/code>3). The following lines create ten threads (4), each performing the lambda expression, which takes <code>counter<\/code> by reference. The lambda expression gets a random number between 100 and 200 (5) and increments the counter exactly as often. The function <code>getRandom<\/code> (6) start with an initial seed and create a uniformly distributed number via the random number generator Mersenne Twister.<\/p>\n<p>In the end, the <code>exp.counter<\/code> (7) should have an approximate value of 1500 because the ten threads increment on average 150 times. Executing the program on the <a href=\"https:\/\/wandbox.org\/\">Wandbox <\/a>online compiler gave me a surprising result.<\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6045\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/12\/atomicReference.png\" alt=\"atomicReference\" width=\"150\" height=\"166\" style=\"display: block; margin-left: auto; margin-right: auto;\" \/><\/p>\n<p>The counter is 0. What is happening? The issue is in line (3). The initialization in the expression <code>std::atomic&lt;int&gt; counter{exp.counter}<\/code> creates a copy. The following small program exemplifies the issue.<\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ atomicRefCopy.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;atomic&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> val{<span style=\"color: #ff6600;\">5<\/span>};\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&amp;<\/span> ref <span style=\"color: #555555;\">=<\/span> val;                     <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>atomic<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span> atomicRef(ref);\r\n    <span style=\"color: #555555;\">++<\/span>atomicRef;                        <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"ref: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> ref <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"atomicRef.load(): \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> atomicRef.load() <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The increment operation (1) does not address the reference<code> ref<\/code> (2). The value of <code>ref<\/code> is not changed.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6046\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/12\/atomicRefCopy.png\" alt=\"atomicRefCopy\" width=\"350\" height=\"190\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/12\/atomicRefCopy.png 432w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/12\/atomicRefCopy-300x163.png 300w\" sizes=\"auto, (max-width: 350px) 100vw, 350px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>Replacing the <code>std::atomic&lt;int&gt; counter{exp.counter}<\/code> with <code>std::atomic_ref&lt;int&gt; counter{exp.counter<\/code>} solves the issue:<\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ atomicReference.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;atomic&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;random&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;thread&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;vector&gt;<\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> ExpensiveToCopy {\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> counter{};\r\n};\r\n \r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">getRandom<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> begin, <span style=\"color: #007788; font-weight: bold;\">int<\/span> end) {\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>random_device seed;        <span style=\"color: #0099ff; font-style: italic;\">\/\/ initial randomness<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>mt19937 engine(seed());    <span style=\"color: #0099ff; font-style: italic;\">\/\/ generator<\/span>\r\n    std<span style=\"color: #555555;\">::<\/span>uniform_int_distribution<span style=\"color: #555555;\">&lt;&gt;<\/span> uniformDist(begin, end);\r\n\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> uniformDist(engine);\r\n}\r\n \r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">count<\/span>(ExpensiveToCopy<span style=\"color: #555555;\">&amp;<\/span> exp) {\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>vector<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span><span style=\"color: #006699; font-weight: bold;\">thread<\/span><span style=\"color: #555555;\">&gt;<\/span> v;\r\n    std<span style=\"color: #555555;\">::<\/span>atomic_ref<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span> counter{exp.counter};\r\n    \r\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #007788; font-weight: bold;\">int<\/span> n <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>; n <span style=\"color: #555555;\">&lt;<\/span> <span style=\"color: #ff6600;\">10<\/span>; <span style=\"color: #555555;\">++<\/span>n) {\r\n        v.emplace_back([<span style=\"color: #555555;\">&amp;<\/span>counter] {\r\n            <span style=\"color: #006699; font-weight: bold;\">auto<\/span> randomNumber <span style=\"color: #555555;\">=<\/span> getRandom(<span style=\"color: #ff6600;\">100<\/span>, <span style=\"color: #ff6600;\">200<\/span>);\r\n            <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #007788; font-weight: bold;\">int<\/span> i <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>; i <span style=\"color: #555555;\">&lt;<\/span> randomNumber; <span style=\"color: #555555;\">++<\/span>i) { <span style=\"color: #555555;\">++<\/span>counter; }\r\n        });\r\n    }\r\n    \r\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #006699; font-weight: bold;\">auto<\/span><span style=\"color: #555555;\">&amp;<\/span> t <span style=\"color: #555555;\">:<\/span> v) t.join();\r\n\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n\r\n    ExpensiveToCopy exp;\r\n    count(exp);\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"exp.counter: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> exp.counter <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    \r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Now, the value of <code>counter<\/code> is as expected:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6047\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/12\/atomicRef.png\" alt=\"atomicRef\" width=\"200\" height=\"173\" style=\"display: block; margin-left: auto; margin-right: auto;\" \/><\/p>\n<h3><span class=\"ez-toc-section\" id=\"To_be_Atomic_or_Not_to_be_Atomic\"><\/span>To be Atomic or Not to be Atomic<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>You may ask me why I didn&#8217;t make the counter atomic in the first place:<\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">struct<\/span> ExpensiveToCopy {\r\n    std<span style=\"color: #555555;\">::<\/span>atomic<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span> counter{};\r\n};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Of course, this is a valid approach, but this approach has a significant downside. Each access to the counter is synchronized, and synchronization is not for free. On the contrary, using a s<code>td::atomic_ref&lt;int&gt; counter<\/code> lets you explicitly control when you need atomic access to the counter. Most of the time, you may only want to read the value of the counter. Consequently, defining it as an atomic is pessimization.<\/p>\n<p>Let me conclude my post with a few more details about the class template&nbsp;<code>std::atomic_ref<\/code>.<\/p>\n<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Specializations_of_std_atomic_ref\"><\/span>Specializations of <code>std::atomic_ref<\/code><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>You can specialize <code>std::atomic_ref<\/code> for user-defined types, use partial specializations for pointer types or full specializations for arithmetic types such as integral or floating-point types.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Primary_Template\"><\/span>Primary Template<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The primary template <code>std::atomic_ref<\/code> can be instantiated with a <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/types\/is_trivially_copyable\">trivially copyable<\/a> type T. Trivially copyable types are either scalar types (arithmetic types, <code>enum'<\/code>s, pointers, member pointers, or <code>std::nullptr_t<\/code>&#8216;s), or trivially copyable classes and arrays of scalar types<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Partial_Specializations_for_Pointer_Types\"><\/span>Partial Specializations for Pointer Types<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The standard provides partial specializations for a pointer type:<code> std::atomic_ref&lt;t*&gt;<\/code>.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Specializations_for_Arithmetic_Types\"><\/span>Specializations for Arithmetic Types<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The standard provides specialization for the integral and floating-point types: <code>std::atomic_ref&lt;arithmetic type&gt;<\/code>.<\/p>\n<ul>\n<li>Character types: <code>char, char8_t<\/code> (C++20), char16_t, char32_t, and <code>wchar_t<\/code><\/li>\n<li>Standard signed integer types: <code>signed char, short, int, long,<\/code> and long long<\/li>\n<li>Standard unsigned integer types: <code>unsigned char, unsigned short, unsigned int, unsigned long<\/code>, and <code>unsigned long long<\/code><\/li>\n<li>Additional integer types, defined in the header <code>&lt;cstdint&gt;<\/code><\/li>\n<li>Standard floating-point types: <code>float<\/code>, <code>double<\/code>, and<code> long double<\/code><\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"All_Atomic_Operations\"><\/span>All Atomic Operations<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>First, here is the list of all operations on <code>std::atomic_ref<\/code>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6048\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/12\/atomicRefFunctions.PNG\" alt=\"atomicRefFunctions\" width=\"650\" height=\"265\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/12\/atomicRefFunctions.PNG 1339w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/12\/atomicRefFunctions-300x122.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/12\/atomicRefFunctions-1024x418.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/12\/atomicRefFunctions-768x313.png 768w\" sizes=\"auto, (max-width: 650px) 100vw, 650px\" \/><\/p>\n<p>The composite assignment operators (<code>+=, -=, |=, &amp;=<\/code>, or<code> ^=<\/code> ) return the new value; the <code>fetch<\/code> variations return the old value.&nbsp;The <code>compare_exchange_strong<\/code> and <code>compare_exchange_weak<\/code> perform an atomic <code>exchange<\/code> if equal and an atomic <code>load<\/code> if not. They return <code>true<\/code> in the success case, otherwise <code>false<\/code>. Each function supports an additional <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/atomic\/memory_order\">memory-ordering argument<\/a>. The default is sequential consistency.<\/p>\n<p>Of course, not all operations are available on all types referenced by <code>std::atomic_ref.<\/code> The table shows the list of all atomic operations depending on the type referenced by <code>std::atomic_ref<\/code>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6049\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/12\/operationsAtomicRef.png\" alt=\"operationsAtomicRef\" width=\"650\" height=\"289\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/12\/operationsAtomicRef.png 1284w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/12\/operationsAtomicRef-300x133.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/12\/operationsAtomicRef-1024x455.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/12\/operationsAtomicRef-768x342.png 768w\" sizes=\"auto, (max-width: 650px) 100vw, 650px\" \/><\/p>\n<h2><span class=\"ez-toc-section\" id=\"i\"><\/span>&nbsp;<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>When you study the last two tables carefully, you notice that you can use <code>std::atomic_ref<\/code> to synchronize threads.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Whats_next\"><\/span>What&#8217;s next?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><code>std::atomic<\/code> and <code>std::atomic_ref<\/code> support in C++20 member functions <code>notify_one<\/code>, <code>notify_all<\/code>, and <code>wait.<\/code> The three functions provide a convenient way to synchronize threads. In my<a href=\"https:\/\/www.modernescpp.com\/index.php\/synchronization-with-atomics-in-c-20\"> next post,<\/a> I will have a closer look at <code>std::atomic<\/code>&nbsp;and, in particular, the thread synchronization with <code>std::atomic<\/code>&#8216;s&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Atomics receives a few essential extensions in C++20. Today, I start with the new data type std::atomic_ref.<\/p>\n","protected":false},"author":21,"featured_media":5945,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[375],"tags":[434],"class_list":["post-6050","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c-20","tag-atomics"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6050","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=6050"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6050\/revisions"}],"predecessor-version":[{"id":6720,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6050\/revisions\/6720"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5945"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=6050"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=6050"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=6050"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}