{"id":97845,"date":"2018-01-19T07:00:00","date_gmt":"2018-01-19T22:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=97845"},"modified":"2019-03-13T01:02:47","modified_gmt":"2019-03-13T08:02:47","slug":"20180119-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20180119-00\/?p=97845","title":{"rendered":"A helper template function to wait for a Win32 condition variable in a loop"},"content":{"rendered":"<p>Win32 <a HREF=\"https:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/ms682052(v=vs.85).aspx\">condition variables<\/a> suffer from the problem of spurious wake-ups, and you will usually wait on a condition variable in a loop. It&#8217;s easier than <a HREF=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20180118-00\/?p=97825\">the case of <code>Wait&shy;On&shy;Address<\/code><\/a> because you hold a lock while checking the condition, so you don&#8217;t have to worry about race conditions against other threads. (The idea is that anybody who wants to cause a change to the condition needs to acquire the same lock. Therefore holding the lock prevents the condition from changing.) <\/p>\n<p>The C++ standard library contains an overload to <a HREF=\"http:\/\/en.cppreference.com\/w\/cpp\/thread\/condition_variable\/wait\">the <code>std::<code><\/code>condition_<code><\/code>variable::<code><\/code>wait<\/code> method<\/a> which takes a predicate. If the predicate returns <code>false<\/code>, then the <code>wait<\/code> will loop back and wait some more. <\/p>\n<p>Let&#8217;s write that same helper function for Win32 condition variables. <\/p>\n<pre>\ntemplate&lt;typename TLambda&gt;\nvoid SleepConditionVariableCSUntil(\n  CONDITION_VARIABLE* conditionVariable,\n  CRITICAL_SECTION*   criticalSection,\n  TLambda&amp;&amp;           is_okay)\n{\n  while (!is_okay()) {\n    SleepConditionVariableCS(conditionVariable, criticalSection, INFINITE);\n  }\n}\n\ntemplate&lt;typename TLambda&gt;\nvoid SleepConditionVariableSharedSRWUntil(\n  CONDITION_VARIABLE* conditionVariable,\n  SRWLOCK*            srwLock,\n  TLambda&amp;&amp;           is_okay)\n{\n  while (!is_okay()) {\n    SleepConditionVariableSRW(conditionVariable, srwLock, INFINITE,\n                              CONDITION_VARIABLE_LOCKMODE_SHARED);\n  }\n}\n\ntemplate&lt;typename TLambda&gt;\nvoid SleepConditionVariableExclusiveSRWUntil(\n  CONDITION_VARIABLE* conditionVariable,\n  SRWLOCK*            srwLock,\n  TLambda&amp;&amp;           is_okay)\n{\n  while (!is_okay()) {\n    SleepConditionVariableSRW(conditionVariable, srwLock, INFINITE, 0);\n  }\n}\n<\/pre>\n<p>I will admit that these helpers aren&#8217;t as useful as the one for <code>Wait&shy;On&shy;Address<\/code> because the loop is very straightforward. It may not be much of a benefit over just writing the loop out manually. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Another case of the spurious wake-up.<\/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-97845","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Another case of the spurious wake-up.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/97845","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=97845"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/97845\/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=97845"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=97845"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=97845"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}