{"id":31323,"date":"2006-05-03T10:00:11","date_gmt":"2006-05-03T10:00:11","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2006\/05\/03\/the-alertable-wait-is-the-non-gui-analog-to-pumping-messages\/"},"modified":"2006-05-03T10:00:11","modified_gmt":"2006-05-03T10:00:11","slug":"the-alertable-wait-is-the-non-gui-analog-to-pumping-messages","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20060503-11\/?p=31323","title":{"rendered":"The alertable wait is the non-GUI analog to pumping messages"},"content":{"rendered":"<p>\nWhen you are doing GUI programming, you well know that\nthe message pump is the primary way of receiving and dispatching\nmessages.\nThe non-GUI analog to the message pump is the alertable wait.\n<\/p>\n<p>\nA user-mode APC is a request for a function to run on a thread\nin user mode.\nYou can explicitly queue an APC to a thread with the\n<code>QueueUserAPC<\/code> function,\nor you can do it implicitly by passing a completion function to\na waitable timer or asynchronous I\/O.\n(That&#8217;s why the code that indicates that a wait was interrupted\nby an APC is <code>WAIT_IO_COMPLETION<\/code>:\nOriginally, the only thing that queued APCs was asynchronous I\/O.)\n<\/p>\n<p>\nOf course, when an APC is queued, the function cannot run immediately.\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2004\/12\/23\/331246.aspx\">\nImagine what the world would be like if it did<\/a>:\nThe function would interrupt the thread in the middle of whatever\nit was doing,\npossibly with unstable data structures,\nleaving the APC function to run at a point where the program\nis in an inconsistent state.\nIf APCs really did run this way,\nit would be pretty much impossible to write a meaningful APC function\nsince it couldn&#8217;t reliably read from or write to any variables\n(since those variables could be unstable),\nnor could it call any functions that read from or wrote to variables.\nGiven these constraints, there isn&#8217;t much left for a function to do.\n<\/p>\n<p>\nInstead, APCs are dispatched when you perform what is known as an\n&#8220;alertable wait&#8221;.\nThe &#8220;Ex&#8221; versions of most wait functions\n(for example, <code>WaitForSingleObjectEx<\/code>,\n<code>WaitForMultipleObjectsEx<\/code>,\n<code>MsgWaitForMultipleObjectsEx<\/code>, and\n<code>SleepEx<\/code>) allow you to specify whether\nyou want to wait alertably.\nIf you do wait alertably, and one or more APCs are queued to the thread,\nthen all the pending APCs are run and the wait operation returns\nwith a code indicating that the wait was interrupted by an APC.\nIf the APC you are waiting for has not yet run (maybe you were\ninterrupted by some unrelated APC), then it is your responsibility to\nrestart the wait and try again.\n<\/p>\n<p>\nWhy doesn&#8217;t the operating system automatically restart the wait?\n&#8220;Imagine what the world would be like if it did&#8221;:\nSuppose you want to issue asynchronous I\/O and then go off and do\nsome other stuff, and then wait for the asynchronous I\/O to complete\nso you can use the result.\n<\/p>\n<pre>\n\/\/ When an asynchronous read completes, we fire off the next\n\/\/ read request. When all done, set fCompleted.\nBOOL fCompleted = FALSE;\nBOOL fSuccess;\nvoid CALLBACK CompletionRoutine(DWORD, DWORD, LPOVERLAPPED)\n{\n if (&lt;finished&gt;) {\n  fSuccess = TRUE;\n  fCompleted = TRUE;\n } else {\n  \/\/ issue the next read in the sequence\n  if (!ReadFileEx(hFile, ..., CompletionRoutine)) {\n   fSuccess = FALSE; \/\/ problem occurred\n   fCompleted = TRUE; \/\/ we're done\n }\n}\n...\n\/\/ start the read cycle\nif (ReadFileEx(hFile, ..., CompletionRoutine)) {\n  DoOtherStuffInTheMeantime();\n  &lt;wait for fCompleted to be set&gt;\n  DoStuffWithResult();\n}\n<\/pre>\n<p>\nHow would you write the &#8220;wait for <code>fCompleted<\/code> to be set&#8221;\nif the operating system auto-restarted waits?\nIf you did an alertable infinite wait, say with\n<code>SleepEx(INFINITE, TRUE)<\/code>,\nthen the APCs would run, the operating system would auto-restart\nthe waits, and the sleep would just run forever.\nYou would be forced to use a non-<code>INFINITE<\/code> sleep\nand poll for the completion.\nBut this has two serious flaws:\nOne is that\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2006\/01\/24\/516808.aspx\">\npolling is bad<\/a>.\nThe second is that the rate at which you poll controls how\nquickly your program reacts to the completion of the read chain.\nHigher polling rates give you better responsiveness but consume more CPU.\n<\/p>\n<p>\nFortunately, waits are not auto-restarted.\nThis gives you a chance to decide for yourself whether you want\nto restart them or not:\n<\/p>\n<pre>\n...\n\/\/ start the read cycle\nif (ReadFileEx(hFile, ..., CompletionRoutine)) {\n  DoOtherStuffInTheMeantime();\n  while (!fCompleted) SleepEx(INFINITE, TRUE);\n  DoStuffWithResult();\n}\n<\/pre>\n<p>\nThe <code>SleepEx<\/code> loop just keeps waiting alertably,\nprocessing APCs, until the completion routine finally decides\nthat it&#8217;s had enough and sets the <code>fCompleted<\/code> flag.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When you are doing GUI programming, you well know that the message pump is the primary way of receiving and dispatching messages. The non-GUI analog to the message pump is the alertable wait. A user-mode APC is a request for a function to run on a thread in user mode. You can explicitly queue an [&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-31323","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>When you are doing GUI programming, you well know that the message pump is the primary way of receiving and dispatching messages. The non-GUI analog to the message pump is the alertable wait. A user-mode APC is a request for a function to run on a thread in user mode. You can explicitly queue an [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/31323","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=31323"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/31323\/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=31323"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=31323"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=31323"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}