{"id":11013,"date":"2011-04-06T07:00:01","date_gmt":"2011-04-06T07:00:01","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2011\/04\/06\/lock-free-algorithms-choosing-a-unique-value-solutions\/"},"modified":"2011-04-06T07:00:01","modified_gmt":"2011-04-06T07:00:01","slug":"lock-free-algorithms-choosing-a-unique-value-solutions","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20110406-01\/?p=11013\/","title":{"rendered":"Lock-free algorithms: Choosing a unique value (solutions)"},"content":{"rendered":"<p>\nLast time, I left a\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2011\/04\/05\/10149783.aspx\">\nwarm-up exercise<\/a>\nconsisting of a code fragment which tries to compute a unique\nprocess-wide value.\nHere it is again:\n<\/p>\n<blockquote CLASS=\"m\">\n<pre>\ndwUniqueId = InterlockedCompareExchange(&amp;g_dwUniqueId,\n                                        g_dwUniqueId+1,\n                                        g_dwUniqueId);\n<\/pre>\n<\/blockquote>\n<p>\nIt may be easier to enumerate what the function does <i>right<\/i>\nrather than what it does wrong.\n<\/p>\n<p>\nUm, the words are correctly-spelled.\n<\/p>\n<p>\nThat&#8217;s about it.\n<\/p>\n<p>\nDamien was the first to note that\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2011\/04\/05\/10149783.aspx#10150008\">\nthe author basically reimplemented <code>Interlocked&shy;Increment<\/code>.\nPoorly<\/a>.\n<\/p>\n<p>\nAs we saw earlier, the algorithm for performing complex calculations with\ninterlocked functions is\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2004\/09\/15\/229915.aspx\">\n(capture, compute, compare-exchange, retry)<\/a>.\nBut the above code didn&#8217;t do any of these things.\n<\/p>\n<p>\nBy failing to capture the values, the code is vulnerable to another\nthread modifying the <code>g_dwUniqueId<\/code> value simultaneously.\nThis means that the computation step can fail,\nbecause the inconsistent reads of <code>g_dwUniqueId<\/code>\nresult in who-knows-what getting passed to the\n<code>Interlocked&shy;Compare&shy;Exchange<\/code> function.\n<\/p>\n<p>\nOkay, they managed to spell\n<code>Interlocked&shy;Compare&shy;Exchange<\/code> correctly.\n<\/p>\n<p>\nAnd then they forgot to retry the operation if the compare-exchange\nfailed,\nwhich means that they will just proceed with whatever value the\n<code>g_dwUniqueId<\/code>\nvariable held at the time of the\n<code>Interlocked&shy;Compare&shy;Exchange<\/code> call.\nIf it just got incremented by another thread, then this thread\nand the other thread will be using the same &#8220;unique&#8221; value.\n<\/p>\n<p>\nJoshua points out that\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2011\/04\/05\/10149783.aspx#10150063\">\ncompiler optimization can prevent the capture from being a true capture<\/a>.\nThough I would put the <code>volatile<\/code> keyword on\n<code>g_dwUniqueId<\/code> rather than <code>scv<\/code>,\nbecause the volatile object is the global variable, not the local.\nMarking the local as volatile forces all accesses to the local to be\nexecuted as written, but the compiler can still optimize the access\nto <code>g_dwUniqueId<\/code>.\n(It might, for example, propagate the value in from a previous read\nearlier in the function.)\n<\/p>\n<p>\nAnd do take into consideration\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2011\/04\/05\/10149783.aspx#10150047\">\nLeo Davidson&#8217;s warning<\/a>:\nThis series of articles is a <i>peek behind the scenes<\/i> series,\nnot a <i>here&#8217;s how you should do it<\/i> series.\nWe&#8217;re taking apart a bunch of toasters to see how they work.\nWhen possible, take advantage of code written by people smarter\nthan you.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Last time, I left a warm-up exercise consisting of a code fragment which tries to compute a unique process-wide value. Here it is again: dwUniqueId = InterlockedCompareExchange(&amp;g_dwUniqueId, g_dwUniqueId+1, g_dwUniqueId); It may be easier to enumerate what the function does right rather than what it does wrong. Um, the words are correctly-spelled. That&#8217;s about it. Damien [&hellip;]<\/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-11013","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Last time, I left a warm-up exercise consisting of a code fragment which tries to compute a unique process-wide value. Here it is again: dwUniqueId = InterlockedCompareExchange(&amp;g_dwUniqueId, g_dwUniqueId+1, g_dwUniqueId); It may be easier to enumerate what the function does right rather than what it does wrong. Um, the words are correctly-spelled. That&#8217;s about it. Damien [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/11013","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=11013"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/11013\/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=11013"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=11013"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=11013"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}