{"id":31434,"date":"2022-12-13T17:00:31","date_gmt":"2022-12-13T17:00:31","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/cppblog\/?p=31434"},"modified":"2022-12-15T10:49:51","modified_gmt":"2022-12-15T10:49:51","slug":"c11-atomics-in-visual-studio-2022-version-17-5-preview-2","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cppblog\/c11-atomics-in-visual-studio-2022-version-17-5-preview-2\/","title":{"rendered":"C11 Atomics in Visual Studio 2022 version 17.5 Preview 2"},"content":{"rendered":"<p>MSVC gained support for C11 and C17 back in <a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/c11-and-c17-standard-support-arriving-in-msvc\">Visual Studio 2019 version 16.8<\/a>, but at the time we left out support for some C11 optional features such as atomics, threads, and complex numbers. We are happy to announce that in Visual Studio 2022 17.5 Preview 2 we are adding an experimental implementation of C11 atomics.<\/p>\n<p>Atomics are available in Visual Studio 2022 version 17.5 Preview 2 with the <code>\/experimental:c11atomics<\/code> flag, in <code>\/std:c11<\/code> mode or later. At the moment only lock-free atomics are supported, but in an upcoming release we will extend this support to include locking atomics as well. Atomics of all the usual built-in C types are lock-free, including <code>long long<\/code> on 32-bit x86. We will continue to define the <code>__STDC_NO_ATOMICS__<\/code> macro even under <code>\/experimental:c11atomics <\/code>until locking atomics are implemented.<\/p>\n<h2>Atomics<\/h2>\n<p>C11 atomics add the <code>&lt;stdatomic.h&gt;<\/code> library header, the <code>_Atomic(T)<\/code> type specifier, and the <code>_Atomic<\/code> &#8220;qualifier&#8221; (which is more of a shortcut for <code>_Atomic(T)<\/code> than a real qualifier).<\/p>\n<p><code>_Atomic(T)<\/code> or <code>_Atomic<\/code> can be used to declare an atomic:<\/p>\n<pre><code class=\"language-c\">_Atomic(int) a; \/\/ using the specifier\r\n_Atomic int a; \/\/ using the qualifier<\/code><\/pre>\n<p>This works for structs as well, for example:<\/p>\n<pre><code class=\"language-c\">struct cat {\r\n   int a;\r\n};\r\n\r\n_Atomic struct cat furball;\r\n_Atomic(struct cat) fuzzball;<\/code><\/pre>\n<p>When you&#8217;re declaring a struct and defining a variable of the same type you can put <code>_Atomic(T)<\/code> and <code>_Atomic<\/code> in a number of places:<\/p>\n<pre><code class=\"language-c\">_Atomic(struct {\r\n    int a;\r\n}) meow;\r\n\r\n_Atomic(struct cat {\r\n    int a;\r\n}) furball;\r\n\r\n_Atomic struct {\r\n    int a;\r\n} purr;\r\n\r\nstruct {\r\n    int a;\r\n} _Atomic purr1;\r\n\r\n_Atomic(struct {\r\n    int a;\r\n}) _Atomic purr2;\r\n\r\n_Atomic struct {\r\n    int a;\r\n} _Atomic purr3;<\/code><\/pre>\n<p>Notice that unlike the <code>_Atomic(T)<\/code> type specifier you can repeat the <code>_Atomic<\/code> qualifier as many times as you like, just like other type-qualifiers. The<code> _Atomic<\/code> qualifier is particularly useful when declaring structs or variables of structure types because it doesn&#8217;t require parentheses. It can also be useful in macros or typedefs because it can be repeated any number of times. In other respects it is identical to the type specifier.<\/p>\n<p>Normal C assignment and compound assignment expressions are atomic on atomic types, and the loads and stores involved are done with sequentially consistent memory ordering. Note that unlike C++&#8217;s <code>std::atomic<\/code> the <code>\/=<\/code>, <code>%=<\/code>, and <code>*=<\/code> operators are provided, and are atomic. The <code>atomic_load_explicit<\/code> and <code>atomic_store_explicit<\/code> library functions allow you to specify a memory order for loads and stores explicitly. Normal C initializers also work on atomic objects, and are not atomic. <code>atomic_init<\/code> can be used to explicitly initialize an atomic, or to later store to the atomic non-atomically.<\/p>\n<p>The library functions above are provided by <code>&lt;stdatomic.h&gt;<\/code>, along with the remaining &#8220;usual&#8221; atomic operations and types. Notice that we are not providing the\u00a0<code> ATOMIC_VAR_INIT<\/code> macro. This macro was deprecated in C17 and removed in C23, and it&#8217;s a bit of a trap for the unaware. If the lack of this macro causes problems in your code please <a href=\"#send-us-your-feedback\">let us know<\/a>.<\/p>\n<h2>C++ <code>&lt;atomic&gt;<\/code> compatibility<\/h2>\n<p>The Microsoft C++ standard library has implemented <a href=\"https:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2020\/p0943r6.html\">P0943R6: Support C atomics in C++<\/a> since Visual Studio 2022 17.1, and our C11 atomics implementation has the same\nABI as the STL&#8217;s C++ atomics. You can share headers that use atomics between C and C++ code and any atomic operations will be correctly ordered with respect to one another. If you do share headers be sure to limit yourself to the subset of syntax that&#8217;s valid in both C and C++; no <code>_Atomic<\/code> qualifier, no calling member functions on <code>_Atomic(T)<\/code> types, no using atomic <code>\/=<\/code> expressions, etc. Because this level of compatibility requires C11 atomics to use the exact same ABI as C++ atomics they also inherit some of the limitations of our C++ atomics, namely:<\/p>\n<ol>\n<li>Our atomics are only lock-free for objects with sizes &lt;= 8 and exactly equal to a power of two. Other implementations allow lock-free operations on non-power of two objects &lt;= 16.<\/li>\n<li>Our locking atomics will have the lock stored <em>inside<\/em> the atomic object, meaning locking atomic objects are bigger than their non-atomic counterparts, and you can&#8217;t cast a pointer to a non-atomic object to a pointer to its atomic equivalent. On the other hand it means you can share locking atomics between processes (using shared memory segments) and get correct synchronization.<\/li>\n<\/ol>\n<p>Codegen for C11 atomics should be almost exactly equivalent to codegen for C++ atomics in release mode, as basic operations are implemented essentially identically. An exception to this is when using C11 atomics without including the stdatomic.h header, like so:<\/p>\n<pre><code class=\"language-c\">int main(void) {\r\n    _Atomic(int) v = 0;\r\n    v += 3;\r\n    return v;\r\n}<\/code><\/pre>\n<p>This will generate code containing a <code>call<\/code> instruction to a support routine implementing atomic increment, even in release mode. Including <code>&lt;stdatomic.h&gt;<\/code>will allow the code to be inlined, as with C++. Code for the library routines is inside the <code>vcruntime.lib<\/code> import library, and there&#8217;s no additional runtime components to distribute. C11 atomics should work fine on all the platforms supported by the Visual C++ Runtime, which are currently Windows 7 and newer.<\/p>\n<h2>Threads<\/h2>\n<p>We are working on supporting <code>&lt;threads.h&gt;<\/code> in an upcoming Visual Studio release. Unlike atomics our implementation of threads will not have the same ABI as C++ threads, although it will likely be possible to include <code>&lt;threads.h&gt;<\/code> from C++ for interoperability. Stay tuned for updates on this feature in calendar year 2023.<\/p>\n<h2>Try them out!<\/h2>\n<p>Once you&#8217;ve installed Visual Studio 2022 17.5 Preview 2 you can try out C11 atomics by adding <code>\/experimental:c11atomics<\/code> and <code>\/std:c11<\/code> or <code>\/std:c17<\/code> to your compile options. Note that we still define <code>__STDC_NO_ATOMICS__<\/code> so if your build system is testing for that you will need to add a special case or change to checking if compiling a translation unit including <code>&lt;stdatomic.h&gt;<\/code> succeeds.<\/p>\n<h2>Send us your feedback<\/h2>\n<p>If you have any thoughts on this feature, or other ideas on how to improve our tools you can leave a comment below. Additionally you can contact us via email at visualcpp@microsoft.com or report any bugs you encounter using <a href=\"https:\/\/developercommunity.visualstudio.com\/\">developer community<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>C11 Atomics in Visual Studio 2022 version 17.5 Preview 2<\/p>\n","protected":false},"author":4807,"featured_media":35994,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[270,1],"tags":[],"class_list":["post-31434","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-announcement","category-cplusplus"],"acf":[],"blog_post_summary":"<p>C11 Atomics in Visual Studio 2022 version 17.5 Preview 2<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/31434","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/users\/4807"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/comments?post=31434"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/31434\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media\/35994"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media?parent=31434"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/categories?post=31434"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/tags?post=31434"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}