{"id":2001,"date":"2014-02-14T13:00:10","date_gmt":"2014-02-14T13:00:10","guid":{"rendered":"http:\/\/writeasync.net\/?p=2001"},"modified":"2014-02-14T06:57:22","modified_gmt":"2014-02-14T06:57:22","slug":"native-inputqueue-thread-safety","status":"publish","type":"post","link":"http:\/\/writeasync.net\/?p=2001","title":{"rendered":"Native InputQueue thread-safety"},"content":{"rendered":"<p>In the <a href=\"http:\/\/writeasync.net\/?p=1981\" title=\"Porting InputQueue to C++\">previous post<\/a>, I introduced my <a href=\"https:\/\/github.com\/brian-dot-net\/writeasync\/commits\/master\/projects\/NativeQueueSample\">port of InputQueue to C++<\/a>. As usual, the unit tests drove the creation of a correct single-threaded implementation but slightly more needed to be done to make the code thread-safe.<\/p>\n<p>The go-to construct for providing a cross-thread mutual exclusion mechanism in Windows is the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/ms682530(v=vs.85).aspx\">critical section<\/a>. Perhaps <a href=\"http:\/\/en.wikipedia.org\/wiki\/C_(programming_language)\">C programmers<\/a> would be satisfied with <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/ms683472(v=vs.85).aspx\"><code>InitializeCriticalSection<\/code><\/a>, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/ms682608(v=vs.85).aspx\"><code>EnterCriticalSection<\/code><\/a>, and <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/ms684169(v=vs.85).aspx\"><code>LeaveCriticalSection<\/code><\/a> but this is the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/hh279654.aspx\">modern era<\/a>! For <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/hh279653.aspx\">exception-safe<\/a>, less error-prone code, we should be using <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/hh438480.aspx\">RAII techniques<\/a>. Conveniently, the PPL provides just the thing &#8212; a wrapper class <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/dd492843.aspx\"><code>critical_section<\/code><\/a> and its associated <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ee427174.aspx\"><code>critical_section::scoped_lock<\/code><\/a>. This will do nicely as a C++ analog to <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.threading.monitor(v=vs.110).aspx\"><code>System.Threading.Monitor<\/code><\/a> and the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/c5kehkcz.aspx\"><code>lock<\/code> statement<\/a>. Here&#8217;s an example of it in action, in the <code>InputQueue::Enqueue<\/code> method:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nvoid Enqueue(T item)\r\n{\r\n    std::unique_ptr&lt;concurrency::task_completion_event&lt;T&gt;&gt; current;\r\n    {\r\n        concurrency::critical_section::scoped_lock lock(syncRoot_);\r\n        if (!pending_)\r\n        {\r\n            items_.push(item);\r\n        }\r\n        else\r\n        {\r\n            current = std::move(pending_);\r\n        }\r\n    }\r\n\r\n    if (current)\r\n    {\r\n        current-&gt;set(item);\r\n    }\r\n}\r\n<\/pre>\n<p>Note the use of <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/b7kfh662.aspx\">scoping braces<\/a> to ensure that the lock is held only as long as necessary and then released (upon destruction) before attempting to set the task completion event.<\/p>\n<p>To gain confidence that the implementation was truly thread-safe, I ported the integration test app from the managed project to native code. The app is supposed to continuously, concurrently, and asynchronously loop, enqueuing and dequeuing items from the queue. Since we don&#8217;t have <code>async<\/code>\/<code>await<\/code> in C++, achieving this is relatively complicated. Thanks to a bit of help from the PPL team, however, the job is made much easier. Using <a href=\"http:\/\/blogs.msdn.com\/b\/nativeconcurrency\/archive\/2012\/05\/09\/how-to-put-a-ppltasks-continuation-chain-into-a-loop.aspx\"><code>create_iterative_task<\/code><\/a>, writing an asynchronous loop is no longer a chore. Compare the two implementations of the enqueue loop, first in C# and then in C++, and note the similarities:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nprivate static async Task EnqueueLoopAsync(IProducerQueue&lt;int&gt; queue, CancellationToken token)\r\n{\r\n    await Task.Yield();\r\n\r\n    int i = 0;\r\n    while (!token.IsCancellationRequested)\r\n    {\r\n        ++i;\r\n        queue.Enqueue(i);\r\n        await Task.Delay(1);\r\n    }\r\n}\r\n<\/pre>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\ntemplate&lt;typename TProducerQueue&gt;\r\nconcurrency::task&lt;void&gt; EnqueueLoopAsync(TProducerQueue &amp; queue, concurrency::cancellation_token token)\r\n{\r\n    return concurrency::extras::create_delayed_task(std::chrono::milliseconds(1), &#x5B;&amp;queue, token]\r\n    {\r\n        shared_ptr&lt;int&gt; i = std::make_shared&lt;int&gt;();\r\n        return concurrency::extras::create_iterative_task(&#x5B;&amp;queue, token, i]()\r\n        {\r\n            if (token.is_canceled())\r\n            {\r\n                return concurrency::task_from_result(false);\r\n            }\r\n\r\n            int next = ++*i;\r\n            queue.Enqueue(next);\r\n            return concurrency::extras::create_delayed_task(std::chrono::milliseconds(1), &#x5B;]() { return true; });\r\n        });\r\n    });\r\n}\r\n<\/pre>\n<p>With C++, you have to be more explicit about how the memory is managed, using <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/bb982026.aspx\"><code>shared_ptr<\/code><\/a> and passing the queue <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/w7049scy.aspx\">by reference<\/a>. But structurally the code is similar. To &#8220;break&#8221; out of the loop, note that we need to return a <code>task<\/code> with a <code>false<\/code> result. In this app, <code>create_delayed_task<\/code> does double duty as an initial &#8220;yield&#8221; mechanism and between every loop iteration as an async rate-limiting delay.<\/p>\n<p>Overall, the PPL is a great tool to have if you want to write correct and efficient asynchronous native code.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the previous post, I introduced my port of InputQueue to C++. As usual, the unit tests drove the creation of a correct single-threaded implementation but slightly more needed to be done to make the code thread-safe. The go-to construct&hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[21,61,101],"tags":[],"class_list":["post-2001","post","type-post","status-publish","format-standard","hentry","category-async","category-concurrency","category-native"],"_links":{"self":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts\/2001","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2001"}],"version-history":[{"count":0,"href":"http:\/\/writeasync.net\/index.php?rest_route=\/wp\/v2\/posts\/2001\/revisions"}],"wp:attachment":[{"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2001"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2001"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/writeasync.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2001"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}