{"id":96255,"date":"2017-05-31T07:00:00","date_gmt":"2017-05-31T21:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=96255"},"modified":"2019-03-13T01:12:19","modified_gmt":"2019-03-13T08:12:19","slug":"20170531-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20170531-00\/?p=96255","title":{"rendered":"Extending our critical section based on WaitOnAddress to support timeouts"},"content":{"rendered":"<p>Let&#8217;s take the <a HREF=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20160825-00\/?p=94165\">critical section we constructed in terms of <code>Wait&shy;On&shy;Address<\/code><\/a> and add two new functions: <\/p>\n<ul>\n<li><code>Try&shy;Enter&shy;Alt&shy;Cs<\/code> tries to enter the critical section if it is either available or is already owned by the current thread. If the critical section is owned by another thread, then the call fails. <\/li>\n<li><code>Try&shy;Enter&shy;Alt&shy;Cs&shy;With&shy;Timeout<\/code> which tries to enter the critical section but gives up after waiting for the specified timeout. <\/li>\n<\/ul>\n<p>The first function is a simplification of the existing <code>Enter&shy;Alt&shy;Cs<\/code> function. It simply gives up if the critical section is not available. <\/p>\n<pre>\nbool TryEnterAltCs(ALTCS* Cs)\n{\n  DWORD ThisThread = GetCurrentThreadId();\n  DWORD PreviousOwner = InterlockedCompareExchangeAcquire(\n               &amp;Cs-&gt;OwnerThread, ThisThread, 0);\n  if (PreviousOwner == 0) {\n    Cs-&gt;ClaimCount++;\n    return true;\n  }\n\n  if (PreviousOwner == ThisThread) {\n    Cs-&gt;ClaimCount++;\n    return true;\n  }\n\n  return false;\n}\n<\/pre>\n<p>The second function is a modification of the existing <code>Enter&shy;Alt&shy;Cs<\/code> function that gives up after waiting too long: <\/p>\n<pre>\n\/\/ Timeout is in milliseconds and cannot be INFINITE.\n<font COLOR=\"blue\">bool<\/font> TryEnterAltCsWithTimeout(ALTCS* Cs, DWORD Timeout)\n{\n  <font COLOR=\"blue\">ULONGLONG Deadline = GetTickCount64() + Timeout;<\/font>\n\n  DWORD ThisThread = GetCurrentThreadId();\n  <font COLOR=\"blue\">DWORD TimeRemaining;\n  do {<\/font>\n    DWORD PreviousOwner = InterlockedCompareExchangeAcquire(\n               &amp;Cs-&gt;OwnerThread, ThisThread, 0);\n    if (PreviousOwner == 0) {\n      Cs-&gt;ClaimCount++;\n      return <font COLOR=\"blue\">true<\/font>;\n    }\n\n    if (PreviousOwner == ThisThread) {\n      Cs-&gt;ClaimCount++;\n      return <font COLOR=\"blue\">true<\/font>;\n    }\n\n    <font COLOR=\"blue\">ULONGLONG Now = GetTickCount64();\n    if (Now &gt;= Deadline) {\n      return false;\n    }\n\n    TimeRemaining = static_cast&lt;DWORD&gt;(Deadline - Now);\n  } while (WaitOnAddress(&amp;Cs-&gt;OwnerThread,\n      &amp;PreviousOwner, sizeof(PreviousOwner), TimeRemaining));\n  return false;<\/font>\n}\n<\/pre>\n<p>The changes we made were to keep track of how much time remains before the deadline. If the deadline passes, then we return <code>false<\/code>. Otherwise, we ask <code>Wait&shy;On&shy;Address<\/code> to wait for the owner to change, or for the timeout to elapse. The function returns <code>FALSE<\/code> if it returned due to a timeout, in which case we break out of the loop and return <code>false<\/code>. Otherwise, we were signaled (possibly spuriously), so we go back and try to claim the critical section again. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ooh, look, a new feature.<\/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-96255","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Ooh, look, a new feature.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/96255","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=96255"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/96255\/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=96255"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=96255"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=96255"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}