{"sha":"d1016a8ef3cd4363ac568fa68e48c267d34d2b8c","node_id":"C_kwDOAiB0YNoAKGQxMDE2YThlZjNjZDQzNjNhYzU2OGZhNjhlNDhjMjY3ZDM0ZDJiOGM","commit":{"author":{"name":"Sean Parent","email":"sean.parent@stlab.cc","date":"2025-01-25T23:47:32Z"},"committer":{"name":"GitHub","email":"noreply@github.com","date":"2025-01-25T23:47:32Z"},"message":"Minor fixes to await and await docs. (#555)\n\n* Improved docs for await and related operations\r\n* Improved implementation of await\r\n* Fixed several test cases for invoke_waiting.","tree":{"sha":"8a0e1305a47ed9ff3702478114c678eb0a019884","url":"https://api.github.com/repos/stlab/stlab/git/trees/8a0e1305a47ed9ff3702478114c678eb0a019884"},"url":"https://api.github.com/repos/stlab/stlab/git/commits/d1016a8ef3cd4363ac568fa68e48c267d34d2b8c","comment_count":0,"verification":{"verified":true,"reason":"valid","signature":"-----BEGIN PGP SIGNATURE-----\n\nwsFcBAABCAAQBQJnlXgUCRC1aQ7uu5UhlAAA7FsQAEZHRod31KzxNHc49c05nxWF\nyi14aYSs9txyPOxmV8PbJVpHDpP7+p8VAStgu6f+nIaECK33pw+IDP3p14mxZpLn\nXkcvM7OoTJmyFiUa0jozALoOq4PTa0BjMb2/yUBmhix1R+ge86yUoBgynwGcu4ZL\nMjbHsrSn/EF95xNFh8QHtOsE5QFVOfbmYO8HC/XnWzy/XkmLDUgcyDUgQgtXiNkh\nWLAQvl+PHjq322YH5S0lrAC6mlqZu4ukR3nIGViuOBO+6NsA0fPa8ClICWWKsqwn\ns1A1sfJJfKg8vK0pvAw++4M2SLosizFQkwmFXb1xsK81oNuH6yO/gtG52ACdL+VN\nzuPIy1wVvyJK/ski5KDbaHBtdSdV+b37JbIJomtOrMhBLjmErvX6xk2UjKRpNMJZ\ns1oKm9v2bfbdlbnoVsMLlLz8mvNsxLsDRx5dj0Gezxf6QZ0a/tCE9BQz7Z6dcgOp\nJ4YkHTFuOpSvF8dF5grtPzOT9c2jVJt8zZOb6A6ba4AZeGE4nhl3q3tmuvTg1GHv\nkRW7AhpvV8jiIE51ZHoUfw5UK677WP8Rfzb50BfYCSj0sjvnwc5iel8jALUPYeTe\nb/WWtXWexUnhgtnA//Heap02Rv6ulGhLn68Gj2jZ6zUCn4RKppJFbyd1vbKva1qu\n8cOFkAOJFJVqlOaV1L8N\n=NPQd\n-----END PGP SIGNATURE-----\n","payload":"tree 8a0e1305a47ed9ff3702478114c678eb0a019884\nparent d80dacd6c3d31e4633ce8aebdb1f2fb28fd93b16\nauthor Sean Parent <sean.parent@stlab.cc> 1737848852 -0800\ncommitter GitHub <noreply@github.com> 1737848852 -0800\n\nMinor fixes to await and await docs. (#555)\n\n* Improved docs for await and related operations\r\n* Improved implementation of await\r\n* Fixed several test cases for invoke_waiting.","verified_at":"2025-01-25T23:52:35Z"}},"url":"https://api.github.com/repos/stlab/stlab/commits/d1016a8ef3cd4363ac568fa68e48c267d34d2b8c","html_url":"https://github.com/stlab/stlab/commit/d1016a8ef3cd4363ac568fa68e48c267d34d2b8c","comments_url":"https://api.github.com/repos/stlab/stlab/commits/d1016a8ef3cd4363ac568fa68e48c267d34d2b8c/comments","author":{"login":"sean-parent","id":2279724,"node_id":"MDQ6VXNlcjIyNzk3MjQ=","avatar_url":"https://avatars.githubusercontent.com/u/2279724?v=4","gravatar_id":"","url":"https://api.github.com/users/sean-parent","html_url":"https://github.com/sean-parent","followers_url":"https://api.github.com/users/sean-parent/followers","following_url":"https://api.github.com/users/sean-parent/following{/other_user}","gists_url":"https://api.github.com/users/sean-parent/gists{/gist_id}","starred_url":"https://api.github.com/users/sean-parent/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sean-parent/subscriptions","organizations_url":"https://api.github.com/users/sean-parent/orgs","repos_url":"https://api.github.com/users/sean-parent/repos","events_url":"https://api.github.com/users/sean-parent/events{/privacy}","received_events_url":"https://api.github.com/users/sean-parent/received_events","type":"User","user_view_type":"public","site_admin":false},"committer":{"login":"web-flow","id":19864447,"node_id":"MDQ6VXNlcjE5ODY0NDQ3","avatar_url":"https://avatars.githubusercontent.com/u/19864447?v=4","gravatar_id":"","url":"https://api.github.com/users/web-flow","html_url":"https://github.com/web-flow","followers_url":"https://api.github.com/users/web-flow/followers","following_url":"https://api.github.com/users/web-flow/following{/other_user}","gists_url":"https://api.github.com/users/web-flow/gists{/gist_id}","starred_url":"https://api.github.com/users/web-flow/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/web-flow/subscriptions","organizations_url":"https://api.github.com/users/web-flow/orgs","repos_url":"https://api.github.com/users/web-flow/repos","events_url":"https://api.github.com/users/web-flow/events{/privacy}","received_events_url":"https://api.github.com/users/web-flow/received_events","type":"User","user_view_type":"public","site_admin":false},"parents":[{"sha":"d80dacd6c3d31e4633ce8aebdb1f2fb28fd93b16","url":"https://api.github.com/repos/stlab/stlab/commits/d80dacd6c3d31e4633ce8aebdb1f2fb28fd93b16","html_url":"https://github.com/stlab/stlab/commit/d80dacd6c3d31e4633ce8aebdb1f2fb28fd93b16"}],"stats":{"total":230,"additions":95,"deletions":135},"files":[{"sha":"0ff60be01459408bc203d78bbe3e134f5a8bc261","filename":"CMakePresets.json","status":"modified","additions":26,"deletions":2,"changes":28,"blob_url":"https://github.com/stlab/stlab/blob/d1016a8ef3cd4363ac568fa68e48c267d34d2b8c/CMakePresets.json","raw_url":"https://github.com/stlab/stlab/raw/d1016a8ef3cd4363ac568fa68e48c267d34d2b8c/CMakePresets.json","contents_url":"https://api.github.com/repos/stlab/stlab/contents/CMakePresets.json?ref=d1016a8ef3cd4363ac568fa68e48c267d34d2b8c","patch":"@@ -21,6 +21,19 @@\n                 \"stlab.coverage\": \"OFF\"\n             }\n         },\n+        {\n+            \"name\": \"debug-cpp20-tsan-ubsan-portable\",\n+            \"description\": \"Ninja Debug Build\",\n+            \"hidden\": false,\n+            \"generator\": \"Ninja\",\n+            \"binaryDir\": \"${sourceDir}/build/ninja-cpp20-debug-thread-undefined\",\n+            \"cacheVariables\": {\n+                \"CMAKE_CXX_STANDARD\": \"20\",\n+                \"CMAKE_BUILD_TYPE\": \"DEBUG\",\n+                \"STLAB_TASK_SYSTEM\": \"portable\",\n+                \"CMAKE_CXX_FLAGS\": \"-fsanitize=thread -fsanitize=undefined\"\n+            }\n+        },\n         {\n             \"name\": \"ninja-cpp20-debug-thread-undefined\",\n             \"description\": \"Ninja Debug Build\",\n@@ -30,8 +43,7 @@\n             \"cacheVariables\": {\n                 \"CMAKE_CXX_STANDARD\": \"20\",\n                 \"CMAKE_BUILD_TYPE\": \"DEBUG\",\n-                \"CMAKE_CXX_FLAGS\": \"-fsanitize=thread -fsanitize=undefined\",\n-                \"CMAKE_LINKER_FLAGS\": \"-fsanitize=thread -fsanitize=undefined\"\n+                \"CMAKE_CXX_FLAGS\": \"-fsanitize=thread -fsanitize=undefined\"\n             }\n         },\n         {\n@@ -45,6 +57,18 @@\n                 \"CMAKE_BUILD_TYPE\": \"DEBUG\"\n             }\n         },\n+        {\n+            \"name\": \"xcode-cpp20-debug-portable\",\n+            \"description\": \"\",\n+            \"hidden\": false,\n+            \"generator\": \"Xcode\",\n+            \"binaryDir\": \"${sourceDir}/build/xcode-cpp20-debug-portable\",\n+            \"cacheVariables\": {\n+                \"CMAKE_CXX_STANDARD\": \"20\",\n+                \"CMAKE_BUILD_TYPE\": \"DEBUG\",\n+                \"STLAB_TASK_SYSTEM\": \"portable\"\n+            }\n+        },\n         {\n             \"name\": \"ninja-cpp17-debug\",\n             \"description\": \"Ninja Debug Build\","},{"sha":"8ea4db3c703ee5df94f9d4cac77ac5fd43014149","filename":"docs/README.md","status":"modified","additions":6,"deletions":44,"changes":50,"blob_url":"https://github.com/stlab/stlab/blob/d1016a8ef3cd4363ac568fa68e48c267d34d2b8c/docs%2FREADME.md","raw_url":"https://github.com/stlab/stlab/raw/d1016a8ef3cd4363ac568fa68e48c267d34d2b8c/docs%2FREADME.md","contents_url":"https://api.github.com/repos/stlab/stlab/contents/docs%2FREADME.md?ref=d1016a8ef3cd4363ac568fa68e48c267d34d2b8c","patch":"@@ -1,54 +1,15 @@\n # `stlab` Documentation\n \n-Pull requests for typos, examples, and other improvements are welcome. To file an issue, please use the [libraries repository](https://github.com/stlab/libraries).\n-\n-# Branch states\n-\n-\\[ These are from the old site - FIX ME \\]\n-\n-- **`master`:** [![master build](https://travis-ci.org/stlab/stlab.github.io.svg?branch=master)](https://travis-ci.org/stlab/stlab.github.io) [![master coverage](https://codecov.io/github/stlab/stlab.github.io/coverage.svg?branch=master)](https://codecov.io/gh/stlab/stlab.github.io/branch/master)\n-\n-- **`develop`:** [![develop build](https://travis-ci.org/stlab/stlab.github.io.svg?branch=develop)](https://travis-ci.org/stlab/stlab.github.io)\n-  [![develop coverage](https://codecov.io/github/stlab/stlab.github.io/coverage.svg?branch=develop)](https://codecov.io/gh/stlab/stlab.github.io/branch/develop)\n-\n-# Building (Mac)\n-\n-You'll need Homebrew to make sure you have the most recent version of Ruby.\n-\n-## Setup\n-\n-1. Clone the repo\n-2. `brew install ruby`\n-3. `sudo gem install bundle jekyll github-pages liquid`\n-\n-Periodically run `gem update` and `bundle update` to make sure you have the latest jekyll tooling.\n-\n-## Building Docs\n+This site is available at [stlab.cc](https://stlab.cc).\n \n-```\n-cd ./docs\n-bundle exec jekyll serve --watch\n-```\n-\n-Documentation viewable at `localhost:4000`\n-Modifying sources should auto-regenerate the documentation\n+Pull requests for typos, examples, and other improvements are welcome. To file an issue, please use the [libraries repository](https://github.com/stlab/libraries).\n \n-## Building Examples\n+## Building the Documentation\n \n-1. `./build.sh` will download dependencies, build, and run all the `*.cpp` files in the `libraries` directory.\n+To run a local Jekyll server, see the instructions in the docker-tools [README](../tools/docker-tools/README.md).\n \n ## Running Hyde in Docker\n \n-The following directory structure is assumed.\n-\n-[ The longer term plan is to migrate the docs for the libraries into the library repo. We also need a plan for the structure of the build directory, a]\n-\n-```\n-.             # This directory stlab.github.io\n-../libraries  # The stlab/libraries repo\n-../builds/hyde      # The cmake build directory configures for building docs\n-```\n-\n Configure the build as follows:\n \n ```\n@@ -81,5 +42,6 @@ cd /mnt/host/libraries/docs\n ```\n \n \\[ this is from the old docs - need to update the docs and script.\n+\n > (or, simply `-u`) to generate the boilerplate for it. Then, fill in any fields marked as `__MISSING__`. Fields marked as `__OPTIONAL__` may be omitted.\n-\\]\n+> \\]"},{"sha":"ee363bc1ec9428d4a8b099b6aa8b60d31bb92466","filename":"docs/include/stlab/algorithm/reverse.hpp/index.md","status":"modified","additions":1,"deletions":1,"changes":2,"blob_url":"https://github.com/stlab/stlab/blob/d1016a8ef3cd4363ac568fa68e48c267d34d2b8c/docs%2Finclude%2Fstlab%2Falgorithm%2Freverse.hpp%2Findex.md","raw_url":"https://github.com/stlab/stlab/raw/d1016a8ef3cd4363ac568fa68e48c267d34d2b8c/docs%2Finclude%2Fstlab%2Falgorithm%2Freverse.hpp%2Findex.md","contents_url":"https://api.github.com/repos/stlab/stlab/contents/docs%2Finclude%2Fstlab%2Falgorithm%2Freverse.hpp%2Findex.md?ref=d1016a8ef3cd4363ac568fa68e48c267d34d2b8c","patch":"@@ -3,7 +3,7 @@ layout: library\n title: stlab/algorithm/reverse.hpp\n hyde:\n   owner: sean-parent\n-  brief: __MISSING__\n+  brief: A collection of algorithms for reversing sequences.\n   tags:\n     - sourcefile\n   library-type: sourcefile"},{"sha":"7e79ba8282a939041d3e6ce998eb2d119a868939","filename":"docs/include/stlab/concurrency/await.hpp/index.md","status":"modified","additions":1,"deletions":1,"changes":2,"blob_url":"https://github.com/stlab/stlab/blob/d1016a8ef3cd4363ac568fa68e48c267d34d2b8c/docs%2Finclude%2Fstlab%2Fconcurrency%2Fawait.hpp%2Findex.md","raw_url":"https://github.com/stlab/stlab/raw/d1016a8ef3cd4363ac568fa68e48c267d34d2b8c/docs%2Finclude%2Fstlab%2Fconcurrency%2Fawait.hpp%2Findex.md","contents_url":"https://api.github.com/repos/stlab/stlab/contents/docs%2Finclude%2Fstlab%2Fconcurrency%2Fawait.hpp%2Findex.md?ref=d1016a8ef3cd4363ac568fa68e48c267d34d2b8c","patch":"@@ -3,7 +3,7 @@ layout: library\n title: stlab/concurrency/await.hpp\n hyde:\n   owner: sean-parent\n-  brief: \"Await provides utilities to synchronously await the value from a `future` and to notify the default executor that a task is waiting. Blocking calls are discouraged because they may lead to deadlocks or thread explosions.\\n\\nThere is a good presentation of the issues [here](https://youtu.be/Z86b3Rd09sE).\\n\"\n+  brief: \"Await provides utilities to await the value from a `future<>` synchronously and to notify the default executor that a task is waiting. Blocking calls are discouraged because they may lead to deadlocks or thread explosions.\\n\\nThere is a good presentation of the issues [here](https://youtu.be/Z86b3Rd09sE).\\n\"\n   tags:\n     - sourcefile\n   library-type: sourcefile"},{"sha":"f3d52add8d488b65d76862d22b702478acc0d5b7","filename":"docs/tools/docker-tools/Dockerfile","status":"modified","additions":17,"deletions":32,"changes":49,"blob_url":"https://github.com/stlab/stlab/blob/d1016a8ef3cd4363ac568fa68e48c267d34d2b8c/docs%2Ftools%2Fdocker-tools%2FDockerfile","raw_url":"https://github.com/stlab/stlab/raw/d1016a8ef3cd4363ac568fa68e48c267d34d2b8c/docs%2Ftools%2Fdocker-tools%2FDockerfile","contents_url":"https://api.github.com/repos/stlab/stlab/contents/docs%2Ftools%2Fdocker-tools%2FDockerfile?ref=d1016a8ef3cd4363ac568fa68e48c267d34d2b8c","patch":"@@ -5,17 +5,17 @@ FROM ubuntu:latest\n \n ARG DEBIAN_FRONTEND=noninteractive\n RUN apt-get update && apt-get install -y \\\n-    apt-utils \\\n-    fswatch \\\n-    g++ \\\n-    git \\\n-    libreadline-dev \\\n-    make \\\n-    nodejs \\\n-    npm \\\n-    rbenv \\\n-    wget \\\n-    zlib1g-dev\n+  apt-utils \\\n+  fswatch \\\n+  g++ \\\n+  git \\\n+  libreadline-dev \\\n+  make \\\n+  nodejs \\\n+  npm \\\n+  rbenv \\\n+  wget \\\n+  zlib1g-dev\n \n RUN apt-get install -y libyaml-dev\n \n@@ -26,9 +26,6 @@ RUN export N_USE_XZ=0; n latest\n RUN npm install -g npm@latest\n RUN npm install -g browser-sync\n \n-###### Temporary #####\n-RUN npm install -g sass-migrator\n-\n # Create a user \"app\" so everything is not running at root\n RUN useradd -ms /bin/bash app\n USER app\n@@ -47,12 +44,12 @@ RUN git clone https://github.com/rbenv/ruby-build.git \"$(rbenv root)\"/plugins/ru\n #  Install ruby\n ARG RUBY_VERSION\n RUN if [ -z ${RUBY_VERSION+x} ]; then \\\n-      rbenv install $(rbenv install -l | grep -v - | tail -1); \\\n-      rbenv global  $(rbenv install -l | grep -v - | tail -1); \\\n-    else \\\n-      rbenv install $RUBY_VERSION; \\\n-      rbenv global $RUBY_VERSION; \\\n-    fi\n+  rbenv install $(rbenv install -l | grep -v - | tail -1); \\\n+  rbenv global  $(rbenv install -l | grep -v - | tail -1); \\\n+  else \\\n+  rbenv install $RUBY_VERSION; \\\n+  rbenv global $RUBY_VERSION; \\\n+  fi\n \n #  Install bundler in global ruby\n RUN (eval \"$(rbenv init -)\"; gem install bundler)\n@@ -62,18 +59,6 @@ RUN (eval \"$(rbenv init -)\"; gem install bundler)\n USER app\n WORKDIR /home/app\n \n-# RUN mkdir ./install\n-# WORKDIR ./install\n-# COPY ./docs/Gemfile .\n-# COPY ./docs/Gemfile.lock .\n-# COPY ./docs/.ruby-version .\n-\n-# RUN (eval \"$(rbenv init -)\"; \\\n-#     bundle config set frozen true; \\\n-#     bundle install)\n-\n-# WORKDIR /home/app\n-\n EXPOSE 3000 3001\n \n # Add version file last to avoid cache invalidation for minor releases"},{"sha":"ddccbd709fe5b84b632775c1e0a69bc46e9f94fb","filename":"docs/tools/docker-tools/README.md","status":"modified","additions":1,"deletions":0,"changes":1,"blob_url":"https://github.com/stlab/stlab/blob/d1016a8ef3cd4363ac568fa68e48c267d34d2b8c/docs%2Ftools%2Fdocker-tools%2FREADME.md","raw_url":"https://github.com/stlab/stlab/raw/d1016a8ef3cd4363ac568fa68e48c267d34d2b8c/docs%2Ftools%2Fdocker-tools%2FREADME.md","contents_url":"https://api.github.com/repos/stlab/stlab/contents/docs%2Ftools%2Fdocker-tools%2FREADME.md?ref=d1016a8ef3cd4363ac568fa68e48c267d34d2b8c","patch":"@@ -3,6 +3,7 @@\n ## Setup\n \n ### Install Docker\n+\n If you don't already have Docker installed, [install Docker](https://docs.docker.com/get-docker/).\n \n ### Building the docker image"},{"sha":"16e0b0783b8bf30e2be8ed0b643b4bcd8616224d","filename":"include/stlab/concurrency/await.hpp","status":"modified","additions":20,"deletions":35,"changes":55,"blob_url":"https://github.com/stlab/stlab/blob/d1016a8ef3cd4363ac568fa68e48c267d34d2b8c/include%2Fstlab%2Fconcurrency%2Fawait.hpp","raw_url":"https://github.com/stlab/stlab/raw/d1016a8ef3cd4363ac568fa68e48c267d34d2b8c/include%2Fstlab%2Fconcurrency%2Fawait.hpp","contents_url":"https://api.github.com/repos/stlab/stlab/contents/include%2Fstlab%2Fconcurrency%2Fawait.hpp?ref=d1016a8ef3cd4363ac568fa68e48c267d34d2b8c","patch":"@@ -36,20 +36,25 @@ inline namespace STLAB_VERSION_NAMESPACE() {\n /**************************************************************************************************/\n \n /**\n-    Assumes f _will wait_ and wakes or adds a thread to the thread pool (to the limit) before\n-    invoking f.\n+    Assumes `f` _will wait_ and wakes or adds a thread to the thread pool (to the limit) before\n+    invoking `f`. If using a condition variable, wrap the duration of the mutex lock in `f` to avoid\n+    deadlocks.\n */\n template <class F>\n auto invoke_waiting(F&& f) {\n #if STLAB_TASK_SYSTEM(PORTABLE)\n     if (!detail::pts().wake()) detail::pts().add_thread();\n #endif\n \n-    std::forward<F>(f)();\n+    return std::forward<F>(f)();\n }\n \n /**************************************************************************************************/\n \n+/// Synchronously wait for the result `x`. If `x` resolves as an exception, the exception is\n+/// rethrown. When using the portable task system, an additional thread is added to the pool if no\n+/// threads are available and the maximum number of threads has not been reached.\n+\n template <class T>\n auto await(future<T>&& x) -> T {\n     if (x.is_ready()) return std::move(x).get_ready(); // if ready, done\n@@ -65,35 +70,15 @@ auto await(future<T>&& x) -> T {\n             condition.notify_one(); // must notify under lock\n         }\n     });\n-\n-#if STLAB_TASK_SYSTEM(PORTABLE)\n-    if (!detail::pts().wake()) detail::pts().add_thread();\n-\n-    /*\n-        If no tasks are available we wait for one tick of the system clock and exponentially\n-        back off on the wait as long as no tasks are available.\n-    */\n-\n-    for (auto backoff{std::chrono::steady_clock::duration{std::chrono::milliseconds{1}}}; true;\n-         backoff *= 2) {\n-        {\n-            std::unique_lock<std::mutex> lock{m};\n-            if (condition.wait_for(lock, backoff, [&] { return result.is_ready(); })) {\n-                return std::move(result).get_ready();\n-            }\n-        }\n-        detail::pts().wake(); // try to wake something to unstick.\n-    }\n-\n-#else\n-\n-    std::unique_lock<std::mutex> lock{m};\n-    condition.wait(lock, [&] { return result.is_ready(); });\n+    invoke_waiting([&] {\n+        std::unique_lock<std::mutex> lock{m};\n+        condition.wait(lock, [&] { return result.is_ready(); });\n+    });\n     return std::move(result).get_ready();\n-\n-#endif\n }\n \n+/// Equivalent to `await(copy(x))`.\n+\n template <class T>\n [[deprecated(\"implicit copy deprecated, use `await(std::move(f))` or `await(stlab::copy(f))`\"\n              \" instead.\")]]\n@@ -128,8 +113,10 @@ struct blocking_get_guarded {\n     }\n \n     auto wait_for(const std::chrono::nanoseconds& timeout) -> future<T> {\n-        std::unique_lock<std::mutex> lock{_mutex};\n-        _timed_out = !_condition.wait_for(lock, timeout, [&] { return _result.valid(); });\n+        _timed_out = !invoke_waiting([&] {\n+            std::unique_lock<std::mutex> lock{_mutex};\n+            return _condition.wait_for(lock, timeout, [&] { return _result.valid(); });\n+        });\n         return _timed_out ? future<T>{} : std::move(_result);\n     }\n };\n@@ -140,10 +127,6 @@ template <class T>\n auto await_for(future<T>&& x, const std::chrono::nanoseconds& timeout) -> future<T> {\n     if (x.is_ready()) return std::move(x);\n \n-#if STLAB_TASK_SYSTEM(PORTABLE)\n-    if (!detail::pts().wake()) detail::pts().add_thread();\n-#endif\n-\n     auto p = std::make_shared<detail::blocking_get_guarded<T>>();\n \n     auto hold = std::move(x).recover(immediate_executor, [_p = stlab::make_weak_ptr(p)](auto&& r) {\n@@ -155,6 +138,8 @@ auto await_for(future<T>&& x, const std::chrono::nanoseconds& timeout) -> future\n     return result.valid() ? std::move(result) : std::move(hold);\n }\n \n+/// Equivalent to `await_for(copy(x), timeout)`.\n+\n template <class T>\n [[deprecated(\"implicit copy deprecated, use `await_for(std::move(f), t)` or\"\n              \" `await_for(stlab::copy(f), t)` instead.\")]]"},{"sha":"5f5872bf6303408b4cb0d1ebec0e322b6f299707","filename":"include/stlab/test/model.hpp","status":"modified","additions":6,"deletions":3,"changes":9,"blob_url":"https://github.com/stlab/stlab/blob/d1016a8ef3cd4363ac568fa68e48c267d34d2b8c/include%2Fstlab%2Ftest%2Fmodel.hpp","raw_url":"https://github.com/stlab/stlab/raw/d1016a8ef3cd4363ac568fa68e48c267d34d2b8c/include%2Fstlab%2Ftest%2Fmodel.hpp","contents_url":"https://api.github.com/repos/stlab/stlab/contents/include%2Fstlab%2Ftest%2Fmodel.hpp?ref=d1016a8ef3cd4363ac568fa68e48c267d34d2b8c","patch":"@@ -18,6 +18,8 @@\n #include <iostream>\n #include <mutex>\n \n+#include <stlab/concurrency/await.hpp>\n+\n /**************************************************************************************************/\n \n namespace stlab {\n@@ -41,9 +43,10 @@ struct annotate_counters {\n     auto remaining() const -> std::size_t { return _copy_ctor + _move_ctor - _dtor + 1; }\n \n     void wait(std::size_t count) {\n-        std::unique_lock<std::mutex> lock(_mutex);\n-        while (count != remaining())\n-            _condition.wait(lock);\n+        stlab::invoke_waiting([&] {\n+            std::unique_lock<std::mutex> lock(_mutex);\n+            _condition.wait(lock, [&] { return count == remaining(); });\n+        });\n     }\n \n     friend inline auto operator<<(std::ostream& out, const annotate_counters& x) -> std::ostream& {"},{"sha":"e3ae2dad39412784f831c287ec294f4ca3c30946","filename":"test/executor_test.cpp","status":"modified","additions":12,"deletions":12,"changes":24,"blob_url":"https://github.com/stlab/stlab/blob/d1016a8ef3cd4363ac568fa68e48c267d34d2b8c/test%2Fexecutor_test.cpp","raw_url":"https://github.com/stlab/stlab/raw/d1016a8ef3cd4363ac568fa68e48c267d34d2b8c/test%2Fexecutor_test.cpp","contents_url":"https://api.github.com/repos/stlab/stlab/contents/test%2Fexecutor_test.cpp?ref=d1016a8ef3cd4363ac568fa68e48c267d34d2b8c","patch":"@@ -5,6 +5,7 @@\n */\n /**************************************************************************************************/\n \n+#include <stlab/concurrency/await.hpp>\n #include <stlab/concurrency/default_executor.hpp>\n #include <stlab/concurrency/serial_queue.hpp>\n \n@@ -106,7 +107,7 @@ BOOST_AUTO_TEST_CASE(all_high_prio_tasks_get_executed) {\n BOOST_AUTO_TEST_CASE(task_system_restarts_after_it_went_pending) {\n     BOOST_TEST_MESSAGE(\"The task system restarts after it went to pending\");\n \n-    atomic_bool done{false};\n+    bool done{false};\n     mutex m;\n     condition_variable cv;\n \n@@ -120,10 +121,10 @@ BOOST_AUTO_TEST_CASE(task_system_restarts_after_it_went_pending) {\n     });\n \n     {\n-        unique_lock<mutex> block{m};\n-        while (!done) {\n-            cv.wait(block);\n-        }\n+        invoke_waiting([&] {\n+            unique_lock<mutex> block{m};\n+            cv.wait(block, [&] { return done; });\n+        });\n     }\n \n     default_executor([&]() noexcept {\n@@ -136,10 +137,10 @@ BOOST_AUTO_TEST_CASE(task_system_restarts_after_it_went_pending) {\n     });\n \n     {\n-        unique_lock<mutex> block{m};\n-        while (done) {\n-            cv.wait(block);\n-        }\n+        invoke_waiting([&] {\n+            unique_lock<mutex> block{m};\n+            cv.wait(block, [&] { return !done; });\n+        });\n     }\n \n     BOOST_REQUIRE(!done);\n@@ -286,9 +287,8 @@ BOOST_AUTO_TEST_CASE(MeasureTiming) {\n         }\n     });\n \n-    unique_lock<mutex> lock{block};\n-    while (!done)\n-        ready.wait(lock);\n+    invoke_waiting(\n+    unique_lock<mutex> lock{block}; [&]{ ready.wait(lock, [&]{ return done; }); });\n \n     while (counter < 3 * iterations) {\n         rest();"},{"sha":"4550d7722c0ef33fd052b317879b0e9fa1a7083b","filename":"test/future_test_helper.hpp","status":"modified","additions":5,"deletions":5,"changes":10,"blob_url":"https://github.com/stlab/stlab/blob/d1016a8ef3cd4363ac568fa68e48c267d34d2b8c/test%2Ffuture_test_helper.hpp","raw_url":"https://github.com/stlab/stlab/raw/d1016a8ef3cd4363ac568fa68e48c267d34d2b8c/test%2Ffuture_test_helper.hpp","contents_url":"https://api.github.com/repos/stlab/stlab/contents/test%2Ffuture_test_helper.hpp?ref=d1016a8ef3cd4363ac568fa68e48c267d34d2b8c","patch":"@@ -199,11 +199,11 @@ class blocking_policy {\n     void set_context(thread_block_context* context) { _context = context; }\n \n     void action() const {\n-        lock_t lock(*_context->_mutex);\n-\n-        while (!_context->_go || !_context->_may_proceed) {\n-            _context->_thread_block.wait(lock);\n-        }\n+        stlab::invoke_waiting([&] {\n+            lock_t lock(*_context->_mutex);\n+            _context->_thread_block.wait(lock,\n+                                         [&] { return _context->_go && _context->_may_proceed; });\n+        });\n     }\n };\n "}]}