{"id":3735,"date":"2020-04-21T16:58:25","date_gmt":"2020-04-21T14:58:25","guid":{"rendered":"https:\/\/mariusbancila.ro\/blog\/?p=3735"},"modified":"2020-04-21T16:58:25","modified_gmt":"2020-04-21T14:58:25","slug":"cpp20-atomic_ref","status":"publish","type":"post","link":"https:\/\/mariusbancila.ro\/blog\/2020\/04\/21\/cpp20-atomic_ref\/","title":{"rendered":"C++20 atomic_ref"},"content":{"rendered":"<p>C++11 provides the atomic operations library that features classes and functions that enable us to perform atomic operations using lock-free mechanisms. There are primarily two class templates in this library, <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/atomic\/atomic\" target=\"_blank\" rel=\"noopener noreferrer\"><tt>std::atomic<\/tt><\/a> and <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/atomic\/atomic_flag\" target=\"_blank\" rel=\"noopener noreferrer\"><tt>std::atomic_flag<\/tt><\/a>. The latter, which defines an atomic boolean type, is guaranteed to always be lock-free and is implemented using the lock-free atomic CPU instructions. The former however, may actually be implemented using mutexes or other locking operations. In this article, we will look at a new class template, introduced in C++20, <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/atomic\/atomic_ref\" target=\"_blank\" rel=\"noopener noreferrer\"><tt>std::atomic_ref<\/tt><\/a>.<\/p>\n<p><!-- more --><\/p>\n<p>The <tt>std::atomic<\/tt> class template has several specializations in C++11:<\/p>\n<ul>\n<li>The primary template that can be instantiated with any type <tt>T<\/tt> that is trivially copyable and satisfies both the <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/named_req\/CopyConstructible\" target=\"_blank\" rel=\"noopener noreferrer\">CopyConstructible<\/a> and <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/named_req\/CopyAssignable\" target=\"_blank\" rel=\"noopener noreferrer\">CopyAssignable<\/a> requirements.<\/li>\n<li>Partial specialization for all pointer types.<\/li>\n<li>Specializations for integral types, that includes the character types, the sign and unsigned integer types, and any additional integral types needed by the typedefs in the header <tt>&lt;cstdint&gt<\/tt>.<\/li>\n<\/ul>\n<p>In C++20, the following specializations have been added:<\/p>\n<ul>\n<li>Specializations for floating-point types <tt>float<\/tt>, <tt>double<\/tt>, and <tt>long double<\/tt>.<\/li>\n<li>Partial specializations <tt>std::atomic&lt;std::shared_ptr&lt;U&gt;&gt;<\/tt> for <tt>std::shared_ptr<\/tt> and <tt>std::atomic&lt;std::weak_ptr&lt;U&gt;&gt;<\/tt> for <tt>std::weak_ptr<\/tt>.<\/li>\n<\/ul>\n<p>What <tt>std::atomic<\/tt> does not support is references. But let&#8217;s start with an example of using <tt>std::atomic<\/tt>.<\/p>\n<pre class=\"lang:c++ decode:true \" >int do_count(int value)\r\n{\r\n   std::atomic&lt;int&gt; counter { value };\r\n\r\n   std::vector&lt;std::thread&gt; threads;\r\n   for (int i = 0; i &lt; 10; ++i)\r\n   {\r\n      threads.emplace_back([&amp;counter]() {\r\n         for (int i = 0; i &lt; 10; ++i)\r\n         {\r\n            ++counter;\r\n            {\r\n               using namespace std::chrono_literals;\r\n               std::this_thread::sleep_for(50ms);\r\n            }\r\n         }\r\n      });\r\n   }\r\n\r\n   for (auto&amp; t : threads) t.join();\r\n\r\n   return counter;\r\n}\r\n\r\nint main()\r\n{\r\n   int result = do_count(0);\r\n   std::cout &lt;&lt; result &lt;&lt; '\\n'; \/\/ prints 100\r\n}<\/pre>\n<p>In this example, the <tt>do_count()<\/tt> function creates 10 threads and each thread increments a variable in a loop. The variable is a shared resource and therefore race conditions must be avoided. The use of the <tt>std::atomic&lt;int&gt;<\/tt> type guarantees race conditions to not occur, although we don&#8217;t necessarily have the guarantee of a lock-free implementation. The <tt>is_lock_free()<\/tt> member function, and the non-member <tt>std::atomic_is_lock_free()<\/tt> function, as well as the compile-time constant <tt>is_always_lock_free<\/tt>, indicate whether the atomic object is implemented using lock-free mechanisms.<\/p>\n<pre class=\"lang:c++ decode:true \" >std::atomic&lt;int&gt; counter { value };\r\nstatic_assert(decltype(counter)::is_always_lock_free, \r\n              \"Atomic int is not lock free!\");   <\/pre>\n<p>However, keep in mind that the standard allows that atomic types are only sometimes lock-free. That means, it&#8217;s possible that we might know only at runtime if an atomic type is lock free, if only some sub-architectures support lock-free atomic access for a given type (such as the CMPXCHG16B instruction on x86-64).<\/p>\n<p>If we change the function above so that the argument is passed by reference, the result changes:<\/p>\n<pre class=\"lang:c++ decode:true \" >void do_count_ref(int&amp; value)\r\n{\r\n   std::atomic&lt;int&gt; counter{ value };\r\n\r\n   std::vector&lt;std::thread&gt; threads;\r\n   for (int i = 0; i &lt; 10; ++i)\r\n   {\r\n      threads.emplace_back([&amp;counter]() {\r\n         for (int i = 0; i &lt; 10; ++i)\r\n         {\r\n            ++counter;\r\n            {\r\n               using namespace std::chrono_literals;\r\n               std::this_thread::sleep_for(50ms);\r\n            }\r\n         }\r\n         });\r\n   }\r\n\r\n   for (auto&amp; t : threads) t.join();\r\n}\r\n\r\nint main()\r\n{\r\n   int value = 0;\r\n   do_count_ref(value);\r\n   std::cout &lt;&lt; value &lt;&lt; '\\n'; \/\/ prints 0\r\n}<\/pre>\n<p>In this case, the value printed to the console is 0 and not 100. This is because <tt>std::atomic<\/tt> does not work with references. It makes a copy of the value it is initialized with, so the <tt>do_count_ref()<\/tt> function does not actually modify its argument.<\/p>\n<p>There are many scenarios where an object should be accessed atomically only in some parts of a program. Performing atomic operations, even lock-free, when they are not necessary could potentially impact performance. This is especially true when working with large arrays. Parallel operations such as initializations and reads do not have conflicting access, but updates require atomic operations. However, with <tt>std::atomic<\/tt>, this is not possible, as shown in the following example:<\/p>\n<pre class=\"lang:c++ decode:true \" >\r\nvoid array_inc(std::vector&lt;int&gt;&amp; arr, size_t const i)\r\n{\r\n   std::atomic&lt;int&gt; elem{ arr[i] };\r\n   elem++;\r\n}\r\n\r\nint main()\r\n{\r\n   std::vector&lt;int&gt; arr{ 1,2,3 };\r\n   array_inc(arr, 0);\r\n   std::cout &lt;&lt; arr[0] &lt;&lt; '\\n'; \/\/ prints 1\r\n}<\/pre>\n<p>The <tt>array_inc<\/tt> function is supposed to increment atomically an element of the provided vector. However, for the same reason mentioned earlier, this does not work, and back in <tt>main()<\/tt>, the <tt>arr<\/tt> vector is left untouched.<\/p>\n<p>To help with this problem, the C++20 standard provides an atomic type that works with references. However, instead of providing a specialization of <tt>std::atomic<\/tt> for references (<tt>std::atomic&lt;T&amp;&gt;<\/tt>), a new class template, called <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/atomic\/atomic_ref\" target=\"_blank\" rel=\"noopener noreferrer\"><tt>std::atomic_ref<\/tt><\/a> is available. This has the exact same interface as <tt>std::atomic<\/tt> and similar specializations:<\/p>\n<ul>\n<li>The primary template that can be instantiated with any type <tt>T<\/tt> that is trivially copyable.<\/li>\n<li>Partial specialization for all pointer types.<\/li>\n<li>Specializations for integral types, that include the character types, the sign and unsigned integer types, and any additional integral types needed by the typedefs in the header <tt>&lt;cstdint&gt<\/tt>.<\/li>\n<li>Specializations for the floating-point types <tt>float<\/tt>, <tt>double<\/tt>, and <tt>long double<\/tt>.<\/li>\n<\/ul>\n<p>There are several requirements when using <tt>std::atomic_ref<\/tt>:<\/p>\n<ul>\n<li>The lifetime of the referred object must exceed the lifetime of the <tt>atomic_ref<\/tt> object itself.<\/li>\n<li>As long as an object is referred in an <tt>atomic_ref<\/tt> instance, it must be exclusively accessed through <tt>atomic_ref<\/tt> instances.<\/li>\n<li>No sub-object of the referred object can be concurrently referenced by any other <tt>atomic_ref<\/tt> object.<\/li>\n<\/ul>\n<p>You also need to keep in mind that:<\/p>\n<ul>\n<li>Whether an implementation of <tt>std::atomic<\/tt> is lock free, does not imply that the corresponding implementation of <tt>atomic_ref<\/tt> is also lock free.<\/li>\n<li>It is possible to modify the referenced value through a <tt>const atomic_ref<\/tt> object.<\/li>\n<\/ul>\n<p>All that we have to do to fix our examples is to replace <tt>std::atomic<\/tt> with <tt>std::atomic_ref<\/tt>. Here is the first:<\/p>\n<pre class=\"lang:c++ decode:true \" >void do_count_ref(int&amp; value)\r\n{\r\n   std::atomic_ref&lt;int&gt; counter{ value };\r\n\r\n   std::vector&lt;std::thread&gt; threads;\r\n   for (int i = 0; i &lt; 10; ++i)\r\n   {\r\n      threads.emplace_back([&amp;counter]() {\r\n         for (int i = 0; i &lt; 10; ++i)\r\n         {\r\n            ++counter;\r\n            {\r\n               using namespace std::chrono_literals;\r\n               std::this_thread::sleep_for(50ms);\r\n            }\r\n         }\r\n         });\r\n   }\r\n\r\n   for (auto&amp; t : threads) t.join();\r\n}<\/pre>\n<p>At the end of the execution of this function, the <tt>value<\/tt> argument will always be 100.<\/p>\n<p>Simillarly, the <tt>array_inc()<\/tt> function will properly update, atomically, the specified element of a vector:<\/p>\n<pre class=\"lang:c++ decode:true \" >\r\nvoid array_inc(std::vector&lt;int&gt;&amp; arr, size_t const i)\r\n{\r\n   std::atomic_ref&lt;int&gt; elem{ arr[i] };\r\n   elem++;\r\n}<\/pre>\n<p>The generated code is also very efficient. This is what the Compiler Explorer is showing when compiling using GCC and the options <tt>-std=gnu++2a -Wall -O3<\/tt>:<\/p>\n<pre class=\"lang:asm decode:true \" >array_inc(std::vector&lt;int, std::allocator&lt;int&gt; &gt;&amp;, unsigned long):\r\n    mov       rax, QWORD PTR [rdi]\r\n    lock add  DWORD PTR [rax+rsi*4], 1\r\n    ret<\/pre>\n<p>I mentioned earlier that is it possible to modify a referenced object through a constant <tt>atomic_ref<\/tt> object. This is because the constness of the <tt>atomic_ref<\/tt> object is shallow and does not affect referenced object. The following snippet provides and example:<\/p>\n<pre class=\"lang:c++ decode:true \" >int a = 42;\r\n{\r\n   const std::atomic_ref ra(a);\r\n   ra++;\r\n}\r\nstd::cout &lt;&lt; a &lt;&lt; '\\n'; \/\/ prints 43<\/pre>\n<p>At this time, <tt>std::atomic_ref<\/tt> is only supported in GCC 10.<br \/>\nThe proposal paper is available here: <a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2018\/p0019r8.html\" target=\"_blank\" rel=\"noopener noreferrer\">Atomic Ref<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>C++11 provides the atomic operations library that features classes and functions that enable us to perform atomic operations using lock-free mechanisms. There are primarily two class templates in this library, <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/atomic\/atomic\" target=\"_blank\" rel=\"noopener noreferrer\"><tt>std::atomic<\/tt><\/a> and <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/atomic\/atomic_flag\" target=\"_blank\" rel=\"noopener noreferrer\"><tt>std::atomic_flag<\/tt><\/a>. The latter, which defines an atomic boolean type, is guaranteed to always be lock-free and is implemented using the lock-free atomic CPU instructions. The former however, may actually be implemented using mutexes or other locking operations. In this article, we will look at a new class template, introduced in C++20, <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/atomic\/atomic_ref\" target=\"_blank\" rel=\"noopener noreferrer\"><tt>std::atomic_ref<\/tt><\/a>.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_uag_custom_page_level_css":"","advgb_blocks_editor_width":"","advgb_blocks_columns_visual_guide":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[7],"tags":[618,451,543],"class_list":["post-3735","post","type-post","status-publish","format-standard","hentry","category-c","tag-atomics","tag-c","tag-c20"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"A look at the new C++20 std::atomic_ref class template that provides atomic operations to a referenced object.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Marius Bancila\"\/>\n\t<meta name=\"keywords\" content=\"c++,c++20,atomics\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/mariusbancila.ro\/blog\/2020\/04\/21\/cpp20-atomic_ref\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"Marius Bancila&#039;s Blog | About code. Mostly on C++\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"C++20 atomic_ref\" \/>\n\t\t<meta property=\"og:description\" content=\"A look at the new C++20 std::atomic_ref class template that provides atomic operations to a referenced object.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/mariusbancila.ro\/blog\/2020\/04\/21\/cpp20-atomic_ref\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-04-21T14:58:25+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-04-21T14:58:25+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"C++20 atomic_ref\" \/>\n\t\t<meta name=\"twitter:description\" content=\"A look at the new C++20 std::atomic_ref class template that provides atomic operations to a referenced object.\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2020\\\/04\\\/21\\\/cpp20-atomic_ref\\\/#article\",\"name\":\"C++20 atomic_ref\",\"headline\":\"C++20 atomic_ref\",\"author\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/author\\\/admin\\\/#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/#organization\"},\"datePublished\":\"2020-04-21T16:58:25+02:00\",\"dateModified\":\"2020-04-21T16:58:25+02:00\",\"inLanguage\":\"en-US\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2020\\\/04\\\/21\\\/cpp20-atomic_ref\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2020\\\/04\\\/21\\\/cpp20-atomic_ref\\\/#webpage\"},\"articleSection\":\"C++, atomics, C++, c++20\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2020\\\/04\\\/21\\\/cpp20-atomic_ref\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/#listItem\",\"name\":\"IT\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/#listItem\",\"position\":2,\"name\":\"IT\",\"item\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/#listItem\",\"name\":\"Software\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/#listItem\",\"position\":3,\"name\":\"Software\",\"item\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/c\\\/#listItem\",\"name\":\"C++\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/#listItem\",\"name\":\"IT\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/c\\\/#listItem\",\"position\":4,\"name\":\"C++\",\"item\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/c\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2020\\\/04\\\/21\\\/cpp20-atomic_ref\\\/#listItem\",\"name\":\"C++20 atomic_ref\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/#listItem\",\"name\":\"Software\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2020\\\/04\\\/21\\\/cpp20-atomic_ref\\\/#listItem\",\"position\":5,\"name\":\"C++20 atomic_ref\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/category\\\/it\\\/software\\\/c\\\/#listItem\",\"name\":\"C++\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/#organization\",\"name\":\"Marius Bancila's Blog\",\"description\":\"About code. Mostly on C++\",\"url\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/author\\\/admin\\\/#author\",\"url\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/author\\\/admin\\\/\",\"name\":\"Marius Bancila\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2020\\\/04\\\/21\\\/cpp20-atomic_ref\\\/#authorImage\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a84dd2831d955c38355ddea55df4df260809b88f36408bc14fd4eab8f7f131c9?s=96&d=mm&r=g\",\"width\":96,\"height\":96,\"caption\":\"Marius Bancila\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2020\\\/04\\\/21\\\/cpp20-atomic_ref\\\/#webpage\",\"url\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2020\\\/04\\\/21\\\/cpp20-atomic_ref\\\/\",\"name\":\"C++20 atomic_ref\",\"description\":\"A look at the new C++20 std::atomic_ref class template that provides atomic operations to a referenced object.\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/2020\\\/04\\\/21\\\/cpp20-atomic_ref\\\/#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/author\\\/admin\\\/#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/author\\\/admin\\\/#author\"},\"datePublished\":\"2020-04-21T16:58:25+02:00\",\"dateModified\":\"2020-04-21T16:58:25+02:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/\",\"name\":\"Marius Bancila's Blog\",\"description\":\"About code. Mostly on C++\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/mariusbancila.ro\\\/blog\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"C++20 atomic_ref","description":"A look at the new C++20 std::atomic_ref class template that provides atomic operations to a referenced object.","canonical_url":"https:\/\/mariusbancila.ro\/blog\/2020\/04\/21\/cpp20-atomic_ref\/","robots":"max-image-preview:large","keywords":"c++,c++20,atomics","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/mariusbancila.ro\/blog\/2020\/04\/21\/cpp20-atomic_ref\/#article","name":"C++20 atomic_ref","headline":"C++20 atomic_ref","author":{"@id":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/#author"},"publisher":{"@id":"https:\/\/mariusbancila.ro\/blog\/#organization"},"datePublished":"2020-04-21T16:58:25+02:00","dateModified":"2020-04-21T16:58:25+02:00","inLanguage":"en-US","mainEntityOfPage":{"@id":"https:\/\/mariusbancila.ro\/blog\/2020\/04\/21\/cpp20-atomic_ref\/#webpage"},"isPartOf":{"@id":"https:\/\/mariusbancila.ro\/blog\/2020\/04\/21\/cpp20-atomic_ref\/#webpage"},"articleSection":"C++, atomics, C++, c++20"},{"@type":"BreadcrumbList","@id":"https:\/\/mariusbancila.ro\/blog\/2020\/04\/21\/cpp20-atomic_ref\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog#listItem","position":1,"name":"Home","item":"https:\/\/mariusbancila.ro\/blog","nextItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/#listItem","name":"IT"}},{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/#listItem","position":2,"name":"IT","item":"https:\/\/mariusbancila.ro\/blog\/category\/it\/","nextItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/#listItem","name":"Software"},"previousItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/#listItem","position":3,"name":"Software","item":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/","nextItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/c\/#listItem","name":"C++"},"previousItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/#listItem","name":"IT"}},{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/c\/#listItem","position":4,"name":"C++","item":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/c\/","nextItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/2020\/04\/21\/cpp20-atomic_ref\/#listItem","name":"C++20 atomic_ref"},"previousItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/#listItem","name":"Software"}},{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/2020\/04\/21\/cpp20-atomic_ref\/#listItem","position":5,"name":"C++20 atomic_ref","previousItem":{"@type":"ListItem","@id":"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/c\/#listItem","name":"C++"}}]},{"@type":"Organization","@id":"https:\/\/mariusbancila.ro\/blog\/#organization","name":"Marius Bancila's Blog","description":"About code. Mostly on C++","url":"https:\/\/mariusbancila.ro\/blog\/"},{"@type":"Person","@id":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/#author","url":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/","name":"Marius Bancila","image":{"@type":"ImageObject","@id":"https:\/\/mariusbancila.ro\/blog\/2020\/04\/21\/cpp20-atomic_ref\/#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/a84dd2831d955c38355ddea55df4df260809b88f36408bc14fd4eab8f7f131c9?s=96&d=mm&r=g","width":96,"height":96,"caption":"Marius Bancila"}},{"@type":"WebPage","@id":"https:\/\/mariusbancila.ro\/blog\/2020\/04\/21\/cpp20-atomic_ref\/#webpage","url":"https:\/\/mariusbancila.ro\/blog\/2020\/04\/21\/cpp20-atomic_ref\/","name":"C++20 atomic_ref","description":"A look at the new C++20 std::atomic_ref class template that provides atomic operations to a referenced object.","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/mariusbancila.ro\/blog\/#website"},"breadcrumb":{"@id":"https:\/\/mariusbancila.ro\/blog\/2020\/04\/21\/cpp20-atomic_ref\/#breadcrumblist"},"author":{"@id":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/#author"},"creator":{"@id":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/#author"},"datePublished":"2020-04-21T16:58:25+02:00","dateModified":"2020-04-21T16:58:25+02:00"},{"@type":"WebSite","@id":"https:\/\/mariusbancila.ro\/blog\/#website","url":"https:\/\/mariusbancila.ro\/blog\/","name":"Marius Bancila's Blog","description":"About code. Mostly on C++","inLanguage":"en-US","publisher":{"@id":"https:\/\/mariusbancila.ro\/blog\/#organization"}}]},"og:locale":"en_US","og:site_name":"Marius Bancila's Blog | About code. Mostly on C++","og:type":"article","og:title":"C++20 atomic_ref","og:description":"A look at the new C++20 std::atomic_ref class template that provides atomic operations to a referenced object.","og:url":"https:\/\/mariusbancila.ro\/blog\/2020\/04\/21\/cpp20-atomic_ref\/","article:published_time":"2020-04-21T14:58:25+00:00","article:modified_time":"2020-04-21T14:58:25+00:00","twitter:card":"summary","twitter:title":"C++20 atomic_ref","twitter:description":"A look at the new C++20 std::atomic_ref class template that provides atomic operations to a referenced object."},"aioseo_meta_data":{"post_id":"3735","title":null,"description":"A look at the new C++20 std::atomic_ref class template that provides atomic operations to a referenced object.","keywords":[{"label":"C++","value":"C++"},{"label":"C++20","value":"C++20"},{"label":"atomics","value":"atomics"}],"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"location":null,"local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"ai":null,"created":"2021-03-18 21:02:54","updated":"2025-12-12 07:54:48","seo_analyzer_scan_date":null,"focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"author_meta":{"display_name":"Marius Bancila","author_link":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/"},"featured_img":null,"jetpack_publicize_connections":[],"uagb_featured_image_src":{"full":false,"thumbnail":false,"medium":false,"medium_large":false,"large":false,"1536x1536":false,"2048x2048":false},"uagb_author_info":{"display_name":"Marius Bancila","author_link":"https:\/\/mariusbancila.ro\/blog\/author\/admin\/"},"uagb_comment_info":0,"uagb_excerpt":"C++11 provides the atomic operations library that features classes and functions that enable us to perform atomic operations using lock-free mechanisms. There are primarily two class templates in this library, std::atomic and std::atomic_flag. The latter, which defines an atomic boolean type, is guaranteed to always be lock-free and is implemented using the lock-free atomic CPU&hellip;","coauthors":[],"tax_additional":{"categories":{"linked":["<a href=\"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/c\/\" class=\"advgb-post-tax-term\">C++<\/a>"],"unlinked":["<span class=\"advgb-post-tax-term\">C++<\/span>"]},"tags":{"linked":["<a href=\"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/c\/\" class=\"advgb-post-tax-term\">atomics<\/a>","<a href=\"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/c\/\" class=\"advgb-post-tax-term\">C++<\/a>","<a href=\"https:\/\/mariusbancila.ro\/blog\/category\/it\/software\/c\/\" class=\"advgb-post-tax-term\">c++20<\/a>"],"unlinked":["<span class=\"advgb-post-tax-term\">atomics<\/span>","<span class=\"advgb-post-tax-term\">C++<\/span>","<span class=\"advgb-post-tax-term\">c++20<\/span>"]}},"comment_count":"0","relative_dates":{"created":"Posted 6 years ago","modified":"Updated 6 years ago"},"absolute_dates":{"created":"Posted on April 21, 2020","modified":"Updated on April 21, 2020"},"absolute_dates_time":{"created":"Posted on April 21, 2020 4:58 pm","modified":"Updated on April 21, 2020 4:58 pm"},"featured_img_caption":"","series_order":"","jetpack_shortlink":"https:\/\/wp.me\/pYNdv-Yf","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/posts\/3735","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/comments?post=3735"}],"version-history":[{"count":15,"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/posts\/3735\/revisions"}],"predecessor-version":[{"id":3750,"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/posts\/3735\/revisions\/3750"}],"wp:attachment":[{"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/media?parent=3735"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/categories?post=3735"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mariusbancila.ro\/blog\/wp-json\/wp\/v2\/tags?post=3735"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}