{"id":96565,"date":"2017-07-10T07:00:00","date_gmt":"2017-07-10T14:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=96565"},"modified":"2017-07-10T07:00:00","modified_gmt":"2017-07-10T14:00:00","slug":"on-the-circular-path-from-raii-to-crazy-town-back-to-raii-thoughts-on-emulating-cs-using-in-c","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20170710-00\/?p=96565","title":{"rendered":"On the circular path from RAII to crazy-town back to RAII: Thoughts on emulating C#&#8217;s using in C++"},"content":{"rendered":"<p><P>\nSome follow-up notes on\n<A HREF=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/\">\nEmulating the C# <CODE>using<\/CODE> keyword in C++<\/A>,\nprimarily for the benefit of\n<A HREF=\"https:\/\/www.reddit.com\/r\/programming\/comments\/6l6b3e\/emulating_the_c_using_keyword_in_c\/\">\npeople from reddit who stumbled into the series and\ndidn&#8217;t understand the context of the discussion<\/A>,\nbecause this was really part 6 of the series begun the previous week,\neven though it wasn&#8217;t labeled as such.\n(And the title itself was a party trick rather than a serious\nproposal.)\n<\/P>\n<P>\nThe main complication that prevented us from using RAII was\nthe use of the\n<A HREF=\"https:\/\/msdn.microsoft.com\/en-us\/library\/dd492418.aspx\">\nParallel Patterns Library<\/A> (PPL)\nto express asynchronous programming in C++.&sup1;\nThe most general pattern for asynchronous programming is that\nyou start an operation, and then specify a callback\nto be invoked when the operation completes.\nIn traditional C-style programming, this callback is\na boring function pointer, coupled with some reference\ndata so the callback has context for why it is being called back.\nC++ provides lambdas which let you express the continuation as\na callback <I>object<\/I>,\nwhich is much more convenient since you can express the control\nflow inline instead of having tiny pieces of control flow scattered\nall over your program.\nAnd lambda capture makes it easy to express what pieces of information\nneeds to be carried forward to the continuation.\n<\/P>\n<P>\nIf we didn&#8217;t have any asynchronous operations, then a basic RAII\nclass would do the trick:\nWhen the RAII class destructs, the cleanup operation occurs.\n(In our example, the cleanup operation is calling <CODE>Close<\/CODE>.)\nThe difficulty in the asynchonous case\nis that it is cumbersome to keep carrying\nthis RAII class forward and preventing it\nfrom destructing until the entire chain of continuations has completed.\nThat&#8217;s where the <CODE>ensure_<\/CODE><CODE>close<\/CODE> and\n<CODE>shared_<\/CODE><CODE>close<\/CODE> classes entered the picture.\nBut you still had to remember to carry them forward.\n<\/P>\n<P>\nThe magical step was the\nintroduction of the not-yet-standard-but-hopefully-soon\n<CODE>co_await<\/CODE> keyword.\nThis\n<A HREF=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/\">\ntransforms the function into a state machine<\/A>,\nwhere each <CODE>co_await<\/CODE> represents\nthe end of a state.\nThe current execution state is saved, and execution of the task\nsuspends.\nWhen the awaited operation completes, the execution state is\nrestored and the function resumes execution.\nThis transformation is very tedious and error-prone to perform\nby hand (especially when there are loops and branches),\nand in particular,\nit preserves RAII semantics:\nThe automatic variables created by the pre-transformed function\nbecome part of the execution state,\nand they are destructed at the &#8220;natural&#8221; time they would have\nbeen destructed prior to transformation.\n<\/P>\n<P>\nAs a result, switching to <CODE>co_await<\/CODE> brings us full circle\nback to plain old RAII.\nBehind the scenes, the compiler is doing the wacky transformations\nthat we tried to mimic with <CODE>ensure_<\/CODE><CODE>close<\/CODE>\nand <CODE>shared_<\/CODE><CODE>close<\/CODE>.\nBut <CODE>co_await<\/CODE> lets us write the code in a far more natural way.\n<\/P>\n<P>\n&sup1;\nThere&#8217;s also\n<CODE>std::future<\/CODE>,\nbut\n<A HREF=\"https:\/\/bartoszmilewski.com\/2009\/03\/03\/broken-promises-c0x-futures\/\">\nits lack of composability<\/A>\nmakes it a poor choice for asynchronous programming.\n<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A trip around the block.<\/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-96565","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>A trip around the block.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/96565","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=96565"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/96565\/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=96565"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=96565"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=96565"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}