{"id":10322,"date":"2024-11-18T09:03:21","date_gmt":"2024-11-18T09:03:21","guid":{"rendered":"https:\/\/www.modernescpp.com\/?p=10322"},"modified":"2025-07-04T16:10:04","modified_gmt":"2025-07-04T16:10:04","slug":"stdexecution","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/stdexecution\/","title":{"rendered":"std::execution"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><strong><code>std::execution<\/code><\/strong>, previously known as executors or Senders\/Receivers, provides \u201c<em>a Standard C++ framework for managing asynchronous execution on generic execution resources<\/em>\u201c. (<a href=\"https:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2024\/p2300r10.html\">P2300R10<\/a>)<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"711\" height=\"491\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2024\/11\/Timeexecution.png\" alt=\"\" class=\"wp-image-10323\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2024\/11\/Timeexecution.png 711w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2024\/11\/Timeexecution-300x207.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2024\/11\/Timeexecution-705x487.png 705w\" sizes=\"auto, (max-width: 711px) 100vw, 711px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Side Note<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Change of plans. My original plan was to present the C++26 library after the core language. However, the implementation status of the library is not good enough. Therefore, I decided to continue with concurrency and<code> std::execution.<\/code> I will present the remaining C++26 features if a compiler implements them.<code>std::execution<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong><code>std::execution<\/code><\/strong> has three key abstractions: schedulers, senders, and receivers, and a set of customizable asynchronous algorithms. My presentation of <code>std::execution<\/code> is based on the proposal <a href=\"https:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2024\/p2300r10.html\">P2300R10<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">First Experiments<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">I used <a href=\"https:\/\/github.com\/NVIDIA\/stdexec\">stdexec <\/a>for my first experiments. This reference implementation from NVIDIA is based on the eighth revision of the proposal. The purpose of this experiment can be found on GitHub.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Provide a proof-of-concept implementation of the design proposed in <a href=\"http:\/\/wg21.link\/p2300\">P2300<\/a>.<\/li>\n\n\n\n<li>Provide early access to developers looking to experiment with the Sender model.<\/li>\n\n\n\n<li>Collaborate with those interested in participating or contributing to the design of P2300 (contributions welcome!).<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\"> You can try out <a href=\"https:\/\/github.com\/NVIDIA\/stdexec\">stdexec<\/a> on <a href=\"https:\/\/godbolt.org\/z\/3cseorf7M\">godbolt<\/a> with the following program.<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #009999\">#include &lt;stdexec\/execution.hpp&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;exec\/static_thread_pool.hpp&gt;<\/span>\n\n<span style=\"color: #007788; font-weight: bold\">int<\/span> <span style=\"color: #CC00FF\">main<\/span>()\n{\n    <span style=\"color: #0099FF; font-style: italic\">\/\/ Declare a pool of 3 worker threads:<\/span>\n    exec<span style=\"color: #555555\">::<\/span>static_thread_pool pool(<span style=\"color: #FF6600\">3<\/span>);\n\n    <span style=\"color: #0099FF; font-style: italic\">\/\/ Get a handle to the thread pool:<\/span>\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> sched <span style=\"color: #555555\">=<\/span> pool.get_scheduler();\n\n    <span style=\"color: #0099FF; font-style: italic\">\/\/ Describe some work:<\/span>\n    <span style=\"color: #0099FF; font-style: italic\">\/\/ Creates 3 sender pipelines that are executed concurrently by passing to `when_all`<\/span>\n    <span style=\"color: #0099FF; font-style: italic\">\/\/ Each sender is scheduled on `sched` using `on` and starts with `just(n)` that creates a<\/span>\n    <span style=\"color: #0099FF; font-style: italic\">\/\/ Sender that just forwards `n` to the next sender.<\/span>\n    <span style=\"color: #0099FF; font-style: italic\">\/\/ After `just(n)`, we chain `then(fun)` which invokes `fun` using the value provided from `just()`<\/span>\n    <span style=\"color: #0099FF; font-style: italic\">\/\/ Note: No work actually happens here. Everything is lazy and `work` is just an object that statically<\/span>\n    <span style=\"color: #0099FF; font-style: italic\">\/\/ represents the work to later be executed<\/span>\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> fun <span style=\"color: #555555\">=<\/span> [](<span style=\"color: #007788; font-weight: bold\">int<\/span> i) { <span style=\"color: #006699; font-weight: bold\">return<\/span> i<span style=\"color: #555555\">*<\/span>i; };\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> work <span style=\"color: #555555\">=<\/span> stdexec<span style=\"color: #555555\">::<\/span>when_all(\n        stdexec<span style=\"color: #555555\">::<\/span>starts_on(sched, stdexec<span style=\"color: #555555\">::<\/span>just(<span style=\"color: #FF6600\">0<\/span>) <span style=\"color: #555555\">|<\/span> stdexec<span style=\"color: #555555\">::<\/span>then(fun)),\n        stdexec<span style=\"color: #555555\">::<\/span>starts_on(sched, stdexec<span style=\"color: #555555\">::<\/span>just(<span style=\"color: #FF6600\">1<\/span>) <span style=\"color: #555555\">|<\/span> stdexec<span style=\"color: #555555\">::<\/span>then(fun)),\n        stdexec<span style=\"color: #555555\">::<\/span>starts_on(sched, stdexec<span style=\"color: #555555\">::<\/span>just(<span style=\"color: #FF6600\">2<\/span>) <span style=\"color: #555555\">|<\/span> stdexec<span style=\"color: #555555\">::<\/span>then(fun))\n    );\n\n    <span style=\"color: #0099FF; font-style: italic\">\/\/ Launch the work and wait for the result<\/span>\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> [i, j, k] <span style=\"color: #555555\">=<\/span> stdexec<span style=\"color: #555555\">::<\/span>sync_wait(std<span style=\"color: #555555\">::<\/span>move(work)).value();\n\n    <span style=\"color: #0099FF; font-style: italic\">\/\/ Print the results:<\/span>\n    std<span style=\"color: #555555\">::<\/span>printf(<span style=\"color: #CC3300\">&quot;%d %d %d<\/span><span style=\"color: #CC3300; font-weight: bold\">\\n<\/span><span style=\"color: #CC3300\">&quot;<\/span>, i, j, k);\n}\n<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Let me convert this program into the revision 10 syntax. You can also try it out on <a href=\"https:\/\/godbolt.org\/z\/7nnKd3sWG\">godbolt<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The program begins by including the necessary headers: <code>&lt;exec\/static_thread_pool.hpp&gt;<\/code> for creating a thread pool, <code>&lt;stdexec\/execution.hpp&gt;<\/code> for execution-related utilities.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In the <code>main<\/code> function, a <code>static_thread_pool pool<\/code> is created with 8 threads. The thread pool executes tasks concurrently. The <code>get_scheduler<\/code> member function of the thread pool is called to obtain a scheduler object s<code>ched.<\/code> The schedule schedules the tasks on the thread pool.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The lambda function <code>fun<\/code> takes an integer <code>i <\/code>as input and returns its square (<code>i * i)<\/code>. This lambda is applied to the input values in the subsequent tasks.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>stdexec::when_all<\/code> function creates a task that waits for the completion of multiple sub-tasks. Each sub-task is created using the <code>stdexec::starts_on<\/code> function, which schedules the task on the specified scheduler <code>sched<\/code>. The <code>stdexec::just<\/code> function creates a task that produces a single value (0, 1, or 2), and the <code>stdexec::then<\/code> function is used to apply the <code>fun<\/code> lambda to this value. The resulting task object is named <code>work<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>stdexec::sync_wait<\/code> function is then called to wait for the completion of the  task synchronously. The <code>std::move<\/code> function transfers ownership of the <code>work<\/code> task to <code>sync_wait<\/code>. The <code>value<\/code> member function is called on the result of <code>sync_wait<\/code> to obtain the values produced by the sub-tasks. These values are unpacked into the variables <code>i<\/code>, <code>j<\/code>, and <code>k<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Finally, the program prints the values of <code>i<\/code>, <code>j<\/code>, and <code>k<\/code> to the console using <code>std::printf<\/code>. These values represent the squares of 0, 1, and 2, respectively.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The following screenshot shows the execution of the program on the Compiler Explorer:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1030\" height=\"436\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2024\/11\/stdexec-1030x436.png\" alt=\"\" class=\"wp-image-10339\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2024\/11\/stdexec-1030x436.png 1030w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2024\/11\/stdexec-300x127.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2024\/11\/stdexec-768x325.png 768w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2024\/11\/stdexec-1536x650.png 1536w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2024\/11\/stdexec-1500x635.png 1500w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2024\/11\/stdexec-705x298.png 705w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2024\/11\/stdexec.png 1727w\" sizes=\"auto, (max-width: 1030px) 100vw, 1030px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">I wrote at the beginning of this post that<code> std::execution<\/code> has three key abstractions: schedulers, senders, and receivers, and a set of customizable asynchronous algorithms. Let me clarify these abstractions:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Execution resources<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>represent the place of execution<\/li>\n\n\n\n<li>don\u2018t need a representation in code<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Scheduler<\/strong>: <code>sched<\/code><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>represent the execution resource<\/li>\n\n\n\n<li>The scheduler concept is defined by a single sender algorithm: <code>schedule<\/code>.<\/li>\n\n\n\n<li>The algorithm schedule returns a sender that will complete on an execution resource determined by the scheduler.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Sender describes work<\/strong>: <code>when_all, starts_on, just, then<\/code><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>send some values if a receiver connected to that sender will eventually receive said values<\/li>\n\n\n\n<li><code>just <\/code>is a so-called sender factory<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Receiver stops the workflow<\/strong>: <code>sync_wait<\/code><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>it supports three channels: value, error, stopped<\/li>\n\n\n\n<li><code>sync_wait<\/code> it&#8217;s a so-called sender consumer<\/li>\n\n\n\n<li>submits the work, blocking the current <code>std::thread<\/code> and returns an optional tuple of values that were sent by the provided sender on its completion of work<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">What&#8217;s Next?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"> After this introduction, I will dive deeper into the set of customizable asynchronous algorithms and preset further examples.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><br><br><br><br><br><br><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>std::execution, previously known as executors or Senders\/Receivers, provides \u201ca Standard C++ framework for managing asynchronous execution on generic execution resources\u201c. (P2300R10) Side Note Change of plans. My original plan was to present the C++26 library after the core language. However, the implementation status of the library is not good enough. Therefore, I decided to continue [&hellip;]<\/p>\n","protected":false},"author":21,"featured_media":10323,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[559],"tags":[561],"class_list":["post-10322","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c26-blog","tag-execution"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/10322","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=10322"}],"version-history":[{"count":26,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/10322\/revisions"}],"predecessor-version":[{"id":10859,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/10322\/revisions\/10859"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/10323"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=10322"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=10322"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=10322"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}