{"id":111265,"date":"2025-06-12T07:00:00","date_gmt":"2025-06-12T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=111265"},"modified":"2025-06-12T08:50:14","modified_gmt":"2025-06-12T15:50:14","slug":"20250612-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20250612-00\/?p=111265","title":{"rendered":"Why does Windows even have <CODE>Interlocked<\/CODE> functions when we have <CODE>std::atomic<\/CODE>?"},"content":{"rendered":"<p>Windows provides a family of functions for performing atomic operations. They have the word <code>Interlocked<\/code> in their name. But why do these functions even exist when we have <code>std::atomic<\/code>?<\/p>\n<p>This is similar to asking <a title=\"Why didn't they use the Space Shuttle to rescue the Apollo 13 astronauts?\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20110119-00\/?p=11723\"> why they didn&#8217;t use the Space Shuttle to rescue the Apollo 13 astronauts<\/a>. You have the history wrong.<\/p>\n<p>Multithreading and atomic operations were not added to the C and C++ languages until C11 and C++11 (respectively), but Windows was doing multithreading since Windows NT 3.1, which released in 1993. Compilers of that era typically did not include intrinsics for atomic operations, so if you needed to do things atomically, you had to call to an outside function.<\/p>\n<p>The Windows <code>Interlocked<\/code> functions were those outside functions. Originally, the only operations were to increment, decrement, or exchange a 4-byte value. (And the increment and decrement operations didn&#8217;t even tell you the result of the increment\/decrement, <a title=\"Why did InterlockedIncrement\/Decrement only return the sign of the result?\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20040506-00\/?p=39463\"> only the sign<\/a>.) Gradually, other operations were added, and the size of the operated-on value was expanded to include pointer-sized values.<\/p>\n<p>In the meantime, compilers realized that maybe they should add intrinsics for atomic operations, and the C and C++ standards committees realized that atomic operations would be a nice thing to standardize, so they added <code>_Atomic<\/code> and <code>std::atomic<\/code>.<\/p>\n<p>So which one should you use?<\/p>\n<p>If you are coding in C or C++, you may as well use the language built-in operations. Nowadays, the compiler can inline the atomic operations, rather than taking the expense of a function call. And they also can optimize around them, or <i>not<\/i> optimize around them, which is probably even more important.<\/p>\n<p>So why do the <code>Interlocked<\/code> functions still exist?<\/p>\n<p>The implementations of the <code>Interlocked<\/code> functions are typically quite small, so leaving them around doesn&#8217;t incur much of a cost. And they are still necessary if you want to perform atomic operations from languages that don&#8217;t have built-in atomics.<\/p>\n<p><b>Bonus chatter<\/b>: Nowadays, the interlocked functions are typically defined for C and C++ consumers in terms of compiler intrinsics, so at the end of the day, it really doesn&#8217;t matter. They all end up turning into compiler intrinsics if you are coding in C and C++.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Well, you have to start somewhere.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-111265","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Well, you have to start somewhere.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/111265","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=111265"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/111265\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=111265"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=111265"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=111265"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}