{"id":92002,"date":"2015-11-09T07:00:00","date_gmt":"2015-11-09T22:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20151109-00\/?p=92002\/"},"modified":"2019-03-13T12:21:29","modified_gmt":"2019-03-13T19:21:29","slug":"20151109-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20151109-00\/?p=92002","title":{"rendered":"Some helper functions for interlocked pointer operations"},"content":{"rendered":"<p>The pointer-related Interlocked functions all operate on <code>void*<\/code>. In practice, though, you are operating on typed pointers. Here are some helper functions to save you a bunch of typing. <\/p>\n<pre>\ntemplate&lt;typename T, typename U&gt;\nT* InterlockedExchangePointerT(\n    T* volatile *target,\n    U value)\n{\n  return reinterpret_cast&lt;T*&gt;(InterlockedExchangePointer(\n    reinterpret_cast&lt;void* volatile*&gt;(target),\n    static_cast&lt;T*&gt;(value)));\n}\n\n\/\/ Repeat for InterlockedExchangePointerAcquire and\n\/\/ InterlockedExchangePointerNoFence.\n\ntemplate&lt;typename T, typename U, typename V&gt;\nT* InterlockedCompareExchangePointerT(\n    T* volatile *target,\n    U exchange,\n    V compare)\n{\n  return reinterpret_cast&lt;T*&gt;(InterlockedCompareExchangePointer(\n    reinterpret_cast&lt;void* volatile*&gt;(target),\n    static_cast&lt;T*&gt;(exchange),\n    static_cast&lt;T*&gt;(compare)));\n}\n\n\/\/ Repeat for InterlockedCompareExchangePointerAcquire,\n\/\/ InterlockedCompareExchangePointerRelease, and\n\/\/ InterlockedCompareExchangePointerNoFence.\n<\/pre>\n<p>The na&iuml;ve versions of these functions would be <\/p>\n<pre>\n<i>template&lt;typename T, typename U&gt;\nT* InterlockedExchangePointerT(\n    T* volatile *target,\n    T* value)\n{\n  return reinterpret_cast&lt;T*&gt;(InterlockedExchangePointer(\n    reinterpret_cast&lt;void* volatile*&gt;(target),\n    value));\n}\n\ntemplate&lt;typename T, typename U, typename V&gt;\nT* InterlockedCompareExchangePointerT(\n    T* volatile *target,\n    T* exchange,\n    T* compare)\n{\n  return reinterpret_cast&lt;T*&gt;(InterlockedCompareExchangePointer(\n    reinterpret_cast&lt;void* volatile*&gt;(target),\n    exchange,\n    compare));\n}<\/i>\n<\/pre>\n<p>but those simpler versions fail on things like <\/p>\n<pre>\nclass Base { ... };\nclass Derived : public Base { ... };\n\nextern Base* b;\n\nDerived* d = new Derived();\nif (InterlockedCompareExchange(&amp;p, d, nullptr)) ...\n<\/pre>\n<p>because the compiler wouldn&#8217;t be able to choose a value for <code>T<\/code>. From the first paramter, it would infer that <code>T = Base<\/code>; from the second parameter, it would infer that <code>T = Derived<\/code>; and from the third parameter, it would give up because it can&#8217;t figure out what value of <code>T<\/code> would result in <code>T*<\/code> being the same as <code>std::nullptr_t<\/code>. <\/p>\n<p>(You can guess how I discovered these limitations of the na&iuml;ve versions.) <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Template-o-rama.<\/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-92002","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Template-o-rama.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/92002","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=92002"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/92002\/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=92002"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=92002"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=92002"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}