{"id":5198,"date":"2017-02-24T06:38:42","date_gmt":"2017-02-24T06:38:42","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/std-future-extensions\/"},"modified":"2023-06-26T12:21:48","modified_gmt":"2023-06-26T12:21:48","slug":"std-future-extensions","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/std-future-extensions\/","title":{"rendered":"std::future Extensions"},"content":{"rendered":"<p>Tasks in the form of promises and futures have in C++11 an ambivalent reputation. On the one hand, they are much easier to use than threads or condition variables; conversely, they have a significant deficiency. They can not be composed. C++20 will overcome this deficiency.<\/p>\n<p><!--more--><\/p>\n<p>Before I write about extended futures, let me say a few words about the advantages of tasks over threads.<\/p>\n<h2>The higher abstraction of tasks<\/h2>\n<p>The key advantage of tasks over threads is that the programmer has only to think about what has to be done and not how&nbsp; &#8211; such as for threads &#8211; it has to be done. The programmer gives the system some job to perform, and the system ensures that the job will be executed by the C++ runtime as smartly as possible. That can mean the job will be executed in the same process, or a separate thread will be started. That can mean that another thread steals the job because it is idle. Under the hood, a thread pool accepts the job and distributes it intelligently. If that is not an abstraction?<\/p>\n<p>I have written a few posts about tasks in the form of <span style=\"font-family: courier new,courier;\">std::async<\/span>, <span style=\"font-family: courier new,courier;\">std::packaged_task<\/span>, <span style=\"font-family: courier new,courier;\">std::promise<\/span>, and <span style=\"font-family: courier new,courier;\">std::future<\/span>. The details are here <a href=\"https:\/\/www.modernescpp.com\/index.php\/tag\/tasks\">tasks<\/a>:&nbsp; But now the future of tasks.<\/p>\n<p>The name extended futures is quite easy to explain. Firstly, the interface of&nbsp;<span style=\"font-family: courier new,courier;\">std::future<\/span> was extended; secondly, there are new functions for creating compensable special futures. I will start with my first point.&nbsp;<\/p>\n<\/p>\n<h2>Extended futures<\/h2>\n<p><span style=\"font-family: courier new,courier;\">std::future<\/span> has three new <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/experimental\/future\">methods.<\/a><\/p>\n<h3>std::future<\/h3>\n<p>An overview of the three new methods.<\/p>\n<ul>\n<li>The <strong><em>unwrapping constructor<\/em> <\/strong>unwraps the outer future of a wrapped future (<span style=\"font-family: courier new,courier;\">future&lt;future&lt;T&gt;&gt;<\/span>).<\/li>\n<li>The predicate <span style=\"font-family: courier new,courier;\"><strong>is_ready <\/strong><\/span>returns whether a shared state is available.<\/li>\n<li>The method <strong><span style=\"font-family: courier new,courier;\">then<\/span><\/strong> attaches a continuation to a future.<\/li>\n<\/ul>\n<p>At first, to something quite sophisticated. The state of the future can be valid or ready.<\/p>\n<h4>valid versus ready<\/h4>\n<ul>\n<li>A future is<strong> valid&nbsp;<\/strong>if the futures has a shared state (with a promise). That has not to be because you can default-construct a&nbsp; <span style=\"font-family: courier new,courier;\">std::future<\/span>. <span style=\"font-family: courier new,courier;\"><\/span><\/li>\n<li>A future is <strong>ready&nbsp;<\/strong>if the shared state is available. Or to say it differently if the promise has already produced its value.<\/li>\n<\/ul>\n<p>Therefore (<span style=\"font-family: courier new,courier;\">valid == true<\/span>) is a requirement for (<span style=\"font-family: courier new,courier;\">ready == true<\/span>).<\/p>\n<p>Whom such as I perceive promise and future as the endpoints of a data channel; I will present my mental picture of validity and readiness. You can see a picture in my post <a href=\"https:\/\/www.modernescpp.com\/index.php\/tasks\">Tasks<\/a>.<\/p>\n<p>The future is valid if there is a data channel to a promise. The future is ready if the promise has already put value into the data channel.<\/p>\n<p>Now, to the method <span style=\"font-family: Courier New,Courier,monospace;\">then<\/span>.<\/p>\n<h4>Continuations with then<\/h4>\n<p><span style=\"font-family: courier new,courier;\">then<\/span> empowers you to attach a future to another future. Here it often happens that a future will be packed into another future. To unwrap the outer future is the job of the <em><span style=\"font-family: courier new,courier;\">unwrapping constructor<\/span>.<\/em><\/p>\n<p><em>Before I show the first code snippet, I have to say a few words about proposal <a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2013\/n3721.pdf\">n3721<\/a>.&nbsp; Most of this post is from the proposal to &#8220;Improvements for std::future&lt;T&gt; and Related APIs&#8221;. That also holds for my examples. Strangely, they often did not use the final <span style=\"font-family: Courier New,Courier,monospace;\">get <\/span>call to get the result from the <span style=\"font-family: Courier New,Courier,monospace;\">res <\/span>future. Therefore, I added to the examples the <span style=\"font-family: Courier New,Courier,monospace;\">res.get<\/span> call and saved the result in a variable <span style=\"font-family: courier new,courier;\">myResult. <\/span>Additionally, I fixed a few typos.<span style=\"font-family: courier new,courier;\"><br \/><\/span><\/em><\/p>\n<div style=\"background: #ffffff none repeat scroll 0% 0%; overflow: auto; width: auto; border-width: 0.1em 0.1em 0.1em 0.8em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0px; line-height: 125%;\"> 1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\n 7\r\n 8\r\n 9\r\n10\r\n11\r\n12<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0px; line-height: 125%;\"><span style=\"color: #0000ff;\">#include &lt;future&gt;<\/span>\r\n<span style=\"color: #0000ff;\">using<\/span> <span style=\"color: #0000ff;\">namespace<\/span> std;\r\n<span style=\"color: #2b91af;\">int<\/span> main() {\r\n\r\n  future&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; f1 = async([]() { <span style=\"color: #0000ff;\">return<\/span> 123; });\r\n  future&lt;string&gt; f2 = f1.then([](future&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; f) {\r\n    <span style=\"color: #0000ff;\">return<\/span> to_string(f.get());      <span style=\"color: #008000;\">\/\/ here .get() won\u2019t block<\/span>\r\n  });\r\n\r\n  <span style=\"color: #0000ff;\">auto<\/span> myResult= f2.get();\r\n\r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>There is a subtle difference between the <span style=\"font-family: courier new,courier;\">to_string(f.get())<\/span> &#8211; call (line 7) and the <span style=\"font-family: courier new,courier;\">f2.get()<\/span>-call in line 10: the first call is non-blocking or asynchronous and the second call is blocking or synchronous. The&nbsp; <span style=\"font-family: courier new,courier;\">f2.get()<\/span> &#8211;&nbsp;&nbsp; call waits until the result of the future-chain is available. This statement will also hold for chains such as <span style=\"font-family: courier new,courier;\">f1.then(&#8230;).then(&#8230;).then(&#8230;).then(&#8230;)<\/span> as it will hold for the composition of extended futures. The final<span style=\"font-family: Courier New,Courier,monospace;\"> f2.get()<\/span> call is blocking.<\/p>\n<h3>std::async, std::packaged_task, and std::promise<\/h3>\n<p>There is not so much to say about the extensions of <span style=\"font-family: courier new,courier;\">std::async, <\/span><span style=\"font-family: courier new,courier;\">std::package_task, <\/span>and<span style=\"font-family: courier new,courier;\"> std::promise<\/span>. I&nbsp; have only to add that all three return in C++20 extended futures.<\/p>\n<p>Therefore, the composition of futures is more exciting. Now we can compose asynchronous tasks.<\/p>\n<h2>Creating new futures<\/h2>\n<p>C++20 gets four new functions for creating special futures. These functions are <span style=\"font-family: courier new,courier;\">std::make_ready_future, std::make_exceptional_future, std::when_all<\/span>, and <span style=\"font-family: courier new,courier;\">std::when_any. <\/span>At first, to the functions<span style=\"font-family: courier new,courier;\"> std::make_ready_future, <\/span>and<span style=\"font-family: courier new,courier;\"> std::make_exceptional_future.<\/span><\/p>\n<h3>std::make_ready_future and std::make_exceptional_future<\/h3>\n<p>Both functions create an immediately ready future. In the first case, the future has a value; in the second case an exception. What seems to be strange makes a lot of sense. The creation of a ready future requires C++11 a promise. That is even necessary if the shared state is immediately available.<\/p>\n<div style=\"background: #ffffff none repeat scroll 0% 0%; overflow: auto; width: auto; border-width: 0.1em 0.1em 0.1em 0.8em;\">\n<pre style=\"margin: 0px; line-height: 125%;\">future&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; compute(<span style=\"color: #2b91af;\">int<\/span> x) {\r\n  <span style=\"color: #0000ff;\">if<\/span> (x &lt; 0) <span style=\"color: #0000ff;\">return<\/span> make_ready_future&lt;<span style=\"color: #2b91af;\">int<\/span>&gt;(-1);\r\n  <span style=\"color: #0000ff;\">if<\/span> (x == 0) <span style=\"color: #0000ff;\">return<\/span> make_ready_future&lt;<span style=\"color: #2b91af;\">int<\/span>&gt;(0);\r\n  future&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; f1 = async([]() { <span style=\"color: #0000ff;\">return<\/span> do_work(x); });\r\n  <span style=\"color: #0000ff;\">return<\/span> f1;\r\n}\r\n<\/pre>\n<\/div>\n<p>Hence, the result must only be calculated using a promise if (<span style=\"font-family: courier new,courier;\">x &gt; 0<\/span>)&nbsp; holds. A short remark. Both functions are the pendant to the return function in a monad. I have already written about this very interesting aspect of <a href=\"https:\/\/www.modernescpp.com\/index.php\/monads-in-c\">extended futures<\/a>. My emphasis in this post was more on functional programming in C++20.<\/p>\n<p>Now, let&#8217;s finally begin with future composition.<\/p>\n<h3>std::when_all und std::when_any<\/h3>\n<p>Both functions have a lot in common.<\/p>\n<p>At first, to the input. Both functions accept a pair of iterators to a future range or an arbitrary number of futures. The big difference is that in the case of the pair of iterators, the futures have to be of the same type; that holds not in the case of the arbitrary number of futures they can have different types, and even <span style=\"font-family: courier new,courier;\">std::future<\/span> and <span style=\"font-family: courier new,courier;\">std::shared_future<\/span> can be used.<\/p>\n<p>The function&#8217;s output depends if a pair of iterators or an arbitrary number of futures (variadic template) was used. Both functions return a future. If a pair of iterators were used, you would get a future of futures in a <span style=\"font-family: Courier New,Courier,monospace;\">std::vector<\/span>:&nbsp;&nbsp; <span style=\"font-family: courier new,courier;\">std::future&lt;std::vector&lt;futureR&gt;&gt;&gt;<\/span>.&nbsp; If you use use a variadic template, you will get a future of futures in a <span style=\"font-family: Courier New,Courier,monospace;\">std::tuple<\/span>: <span style=\"font-family: courier new,courier;\">std::future&lt;std::tuple&lt;future&lt;R0&gt;, future&lt;R1&gt;, &#8230; &gt;&gt;<\/span>.<span style=\"font-family: courier new,courier;\"><br \/><\/span><\/p>\n<p>That was it with their commonalities. The future that both functions return will be ready if all input futures (<span style=\"font-family: Courier New,Courier,monospace;\">when_all<\/span>), or if any of (<span style=\"font-family: Courier New,Courier,monospace;\">when_any<\/span>) the input futures is ready.<\/p>\n<p>The following two examples show the usage of <span style=\"font-family: Courier New,Courier,monospace;\">when_all<\/span> and <span style=\"font-family: Courier New,Courier,monospace;\">when_any<\/span>.<\/p>\n<p>&nbsp;<\/p>\n<h4>when_all<\/h4>\n<div style=\"background: #ffffff none repeat scroll 0% 0%; overflow: auto; width: auto; border-width: 0.1em 0.1em 0.1em 0.8em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0px; line-height: 125%;\"> 1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\n 7\r\n 8\r\n 9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0px; line-height: 125%;\"><span style=\"color: #0000ff;\">#include &lt;future&gt;<\/span>\r\n<span style=\"color: #0000ff;\">using<\/span> <span style=\"color: #0000ff;\">namespace<\/span> std;\r\n\r\n<span style=\"color: #2b91af;\">int<\/span> main() {\r\n\r\n  shared_future&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; shared_future1 = async([] { <span style=\"color: #0000ff;\">return<\/span> intResult(125); });\r\n  future&lt;string&gt; future2 = async([]() { <span style=\"color: #0000ff;\">return<\/span> stringResult(<span style=\"color: #a31515;\">\"hi\"<\/span>); });\r\n\r\n  future&lt;tuple&lt;shared_future&lt;<span style=\"color: #2b91af;\">int<\/span>&gt;, future&lt;string&gt;&gt;&gt; all_f = when_all(shared_future1, future2);\r\n\r\n  future&lt;<span style=\"color: #2b91af;\">int<\/span>&gt; result = all_f.then([](future&lt;tuple&lt;shared_future&lt;<span style=\"color: #2b91af;\">int<\/span>&gt;,\r\n                                                 future&lt;string&gt;&gt;&gt; f){ <span style=\"color: #0000ff;\">return<\/span> doWork(f.get()); });\r\n\r\n  <span style=\"color: #0000ff;\">auto<\/span> myResult= result.get();\r\n\r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The future<span style=\"font-family: Courier New,Courier,monospace;\"> all_f<\/span> (line 9) composes both futures<span style=\"font-family: courier new,courier;\"> shared_future1<\/span> (line 6) and <span style=\"font-family: courier new,courier;\">future2<\/span> (Zeile 7).&nbsp; The future <span style=\"font-family: courier new,courier;\">result<\/span> in line 11 will be executed if all underlying futures are ready<em><\/em>. In this case, the future <span style=\"font-family: courier new,courier;\">all_f <\/span>in line 12 will be executed. The result is available in the future and can be used in line 14.<\/p>\n<h4>when_any<\/h4>\n<p>The future in <span style=\"font-family: courier new,courier;\">when_any<\/span> can be taken by <span style=\"font-family: courier new,courier;\">result<\/span> in line 11. <span style=\"font-family: Courier New,Courier,monospace;\">result <\/span>provides the information which input future is ready. If you don&#8217;t use<span style=\"font-family: Courier New,Courier,monospace;\"> when_any_result<\/span>, you must ask each future if it is ready. That is tedious.<\/p>\n<div style=\"background: #ffffff none repeat scroll 0% 0%; overflow: auto; width: auto; border-width: 0.1em 0.1em 0.1em 0.8em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0px; line-height: 125%;\"> 1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\n 7\r\n 8\r\n 9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0px; line-height: 125%;\"><span style=\"color: #0000ff;\">#include &lt;future&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;vector&gt;<\/span>\r\n\r\n<span style=\"color: #0000ff;\">using<\/span> <span style=\"color: #0000ff;\">namespace<\/span> std;\r\n\r\n<span style=\"color: #2b91af;\">int<\/span> main(){\r\n\r\n  vector&lt;future&lt;<span style=\"color: #2b91af;\">int<\/span>&gt;&gt; v{ .... };\r\n  <span style=\"color: #0000ff;\">auto<\/span> future_any = when_any(v.begin(), v.end());\r\n\r\n  when_any_result&lt;vector&lt;future&lt;<span style=\"color: #2b91af;\">int<\/span>&gt;&gt;&gt; result= future_any.get();\r\n\r\n  future&lt;<span style=\"color: #2b91af;\">int<\/span>&gt;&amp; ready_future = result.futures[result.index];\r\n\r\n  <span style=\"color: #0000ff;\">auto<\/span> myResult= ready_future.get();\r\n\r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>&nbsp;<\/p>\n<p><span style=\"font-family: courier new,courier;\">future_any<\/span> is the future that will be ready if one of the input futures is ready.&nbsp; <span style=\"font-family: courier new,courier;\">future_any.get()<\/span> in line 11 returns the future&nbsp; <span style=\"font-family: courier new,courier;\">result<\/span>. By using <span style=\"font-family: courier new,courier;\">result.futures[result.index]<\/span> (line 13), you have the ready future, and thanks to <span style=\"font-family: Courier New,Courier,monospace;\">ready_future.get<\/span>(), you can ask for the result of the job.<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>Latches and barriers support it to synchronize threads via a counter. I will present them in the <a href=\"https:\/\/www.modernescpp.com\/index.php\/latches-and-barriers\">next post<\/a>.<\/p>\n<p>Two years later, the future of the futures changed a lot because of executores. Here are the details of <a href=\"https:\/\/www.modernescpp.com\/index.php\/a-short-detour-executors\">executors<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Tasks in the form of promises and futures have in C++11 an ambivalent reputation. On the one hand, they are much easier to use than threads or condition variables; conversely, they have a significant deficiency. They can not be composed. C++20 will overcome this deficiency.<\/p>\n","protected":false},"author":21,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[367],"tags":[482,446],"class_list":["post-5198","post","type-post","status-publish","format-standard","hentry","category-multithreading-c-17-and-c-20","tag-outdated","tag-tasks"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5198","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=5198"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5198\/revisions"}],"predecessor-version":[{"id":6884,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5198\/revisions\/6884"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5198"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5198"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5198"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}