{"sha":"facbd553cca8774d9df4fa01ad1d9a832d36eb1e","node_id":"C_kwDOAiB0YNoAKGZhY2JkNTUzY2NhODc3NGQ5ZGY0ZmEwMWFkMWQ5YTgzMmQzNmViMWU","commit":{"author":{"name":"Sean Parent","email":"sean.parent@stlab.cc","date":"2024-03-04T19:44:29Z"},"committer":{"name":"GitHub","email":"noreply@github.com","date":"2024-03-04T19:44:29Z"},"message":"General Cleanup (#539)\n\n* Some lint fixes for the chain library CI.\r\n\r\n* Cleanup\r\n\r\n- Cleaned up mutex usage in await to eliminate a flag, and directly protect the element being modified.\r\n- Fixed a memory leak in Windows if scheduling work fails in the default executor.\r\n- Made package_task<> move-only which simplifies promise by removing promise count.\r\n- Removed unused reduction_failed error code.\r\n- Added a reduction test for future<future<void>>","tree":{"sha":"1aeabec5c87f9f51c66963c0bc6c7ac0be14a697","url":"https://api.github.com/repos/stlab/stlab/git/trees/1aeabec5c87f9f51c66963c0bc6c7ac0be14a697"},"url":"https://api.github.com/repos/stlab/stlab/git/commits/facbd553cca8774d9df4fa01ad1d9a832d36eb1e","comment_count":0,"verification":{"verified":true,"reason":"valid","signature":"-----BEGIN PGP SIGNATURE-----\n\nwsFcBAABCAAQBQJl5iSdCRC1aQ7uu5UhlAAAVc0QAFWTcF1cUNFFh7EjGynhzudO\nVHAc3wXsJKNjnYL5IKTPZ7tjKN32Zss9OgxFqLXHb1OSq/AcDv5Qp1PYzKsBSe1C\ns6V+mNZsBBBXj1RitQWGVJTD8kT5ASWoOeRWtmuHJzds/MWGj0dOgFRwDfDO+9vo\nTbpkdYxdK+KCwjPMlTLKD15iEFPspsI64HwB26aTXqb+vbk2FcG72JJE3sfnCYjB\n8YRy2xxIMZ/m5tBEUa/ABGsE+7A7HTjnRw2ESZlAS4QX0+ZoadodpjxtclwebslT\n45jMKhGOv4BZoMMhemrCr6in8gkhKx8QhW1pQOhCGOspAEs+t9Z5ypfMqNCwpYJj\niHbJCR0W1H5dfKCFTlB4VHHyn5nThKi4B/Q+T7/elHlHWl4td+xe7tNcxzb4Qibk\ngknjTZXk+drkSmEf+1ALyhmVBna2W/ctpRqhVTG7rjU9uryaihppBoEeaVEWtc6C\nXEmqfUPv/pD/sFar3+m+3C5rCXV6Ap3wAY3+ISGuRhjz8c9CI012Lb0bxWPr6YOH\n3zz41rU+GeCS2brwU+ePKAwZ5J+tDdUqiUMMXbSK0HqNC0F8KE/hdaA1aoum1g1I\nnlubi4uTIHbil1W72yUj/BEInBRuVkJH71AC5b5HwXxK94Afe8LbkHLM/bvwcmn+\ntB80uZdv0v/SNbBLH8/A\n=82OI\n-----END PGP SIGNATURE-----\n","payload":"tree 1aeabec5c87f9f51c66963c0bc6c7ac0be14a697\nparent bc092d5b7384f21dc63db366d2f14cb9ec41e83f\nauthor Sean Parent <sean.parent@stlab.cc> 1709581469 -0600\ncommitter GitHub <noreply@github.com> 1709581469 -0600\n\nGeneral Cleanup (#539)\n\n* Some lint fixes for the chain library CI.\r\n\r\n* Cleanup\r\n\r\n- Cleaned up mutex usage in await to eliminate a flag, and directly protect the element being modified.\r\n- Fixed a memory leak in Windows if scheduling work fails in the default executor.\r\n- Made package_task<> move-only which simplifies promise by removing promise count.\r\n- Removed unused reduction_failed error code.\r\n- Added a reduction test for future<future<void>>\r\n\r\n","verified_at":"2024-11-07T16:47:51Z"}},"url":"https://api.github.com/repos/stlab/stlab/commits/facbd553cca8774d9df4fa01ad1d9a832d36eb1e","html_url":"https://github.com/stlab/stlab/commit/facbd553cca8774d9df4fa01ad1d9a832d36eb1e","comments_url":"https://api.github.com/repos/stlab/stlab/commits/facbd553cca8774d9df4fa01ad1d9a832d36eb1e/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":"bc092d5b7384f21dc63db366d2f14cb9ec41e83f","url":"https://api.github.com/repos/stlab/stlab/commits/bc092d5b7384f21dc63db366d2f14cb9ec41e83f","html_url":"https://github.com/stlab/stlab/commit/bc092d5b7384f21dc63db366d2f14cb9ec41e83f"}],"stats":{"total":108,"additions":61,"deletions":47},"files":[{"sha":"97bb58f6e417036052b8b2b6cd52c4fec832eb78","filename":"stlab/concurrency/await.hpp","status":"modified","additions":6,"deletions":12,"changes":18,"blob_url":"https://github.com/stlab/stlab/blob/facbd553cca8774d9df4fa01ad1d9a832d36eb1e/stlab%2Fconcurrency%2Fawait.hpp","raw_url":"https://github.com/stlab/stlab/raw/facbd553cca8774d9df4fa01ad1d9a832d36eb1e/stlab%2Fconcurrency%2Fawait.hpp","contents_url":"https://api.github.com/repos/stlab/stlab/contents/stlab%2Fconcurrency%2Fawait.hpp?ref=facbd553cca8774d9df4fa01ad1d9a832d36eb1e","patch":"@@ -97,15 +97,12 @@ T await(future<T> x) {\n \n     std::mutex m;\n     std::condition_variable condition;\n-    bool flag{false};\n-\n     future<T> result;\n \n     auto hold = std::move(x).recover(immediate_executor, [&](future<T>&& r) {\n-        result = std::move(r);\n         {\n             std::unique_lock<std::mutex> lock{m};\n-            flag = true;\n+            result = std::move(r);\n             condition.notify_one(); // must notify under lock\n         }\n     });\n@@ -122,23 +119,20 @@ T await(future<T> x) {\n          backoff *= 2) {\n         {\n             std::unique_lock<std::mutex> lock{m};\n-            if (condition.wait_for(lock, backoff, [&] { return flag; })) {\n-                break;\n+            if (condition.wait_for(lock, backoff, [&] { return result.is_ready(); })) {\n+                return detail::_get_ready_future<T>{}(std::move(result));\n             }\n         }\n         detail::pts().wake(); // try to wake something to unstick.\n     }\n \n #else\n \n-    {\n-        std::unique_lock<std::mutex> lock{m};\n-        condition.wait(lock, [&] { return flag; });\n-    }\n+    std::unique_lock<std::mutex> lock{m};\n+    condition.wait(lock, [&] { return result.is_ready(); });\n+    return detail::_get_ready_future<T>{}(std::move(result));\n \n #endif\n-\n-    return detail::_get_ready_future<T>{}(std::move(result));\n }\n \n namespace detail {"},{"sha":"be370f0cf1184f9576fbf432bc2972f1049aa613","filename":"stlab/concurrency/default_executor.hpp","status":"modified","additions":14,"deletions":9,"changes":23,"blob_url":"https://github.com/stlab/stlab/blob/facbd553cca8774d9df4fa01ad1d9a832d36eb1e/stlab%2Fconcurrency%2Fdefault_executor.hpp","raw_url":"https://github.com/stlab/stlab/raw/facbd553cca8774d9df4fa01ad1d9a832d36eb1e/stlab%2Fconcurrency%2Fdefault_executor.hpp","contents_url":"https://api.github.com/repos/stlab/stlab/contents/stlab%2Fconcurrency%2Fdefault_executor.hpp?ref=facbd553cca8774d9df4fa01ad1d9a832d36eb1e","patch":"@@ -19,7 +19,9 @@\n #include <cassert>\n #include <chrono>\n #include <functional>\n+#include <memory>\n #include <type_traits>\n+#include <utility>\n \n #if STLAB_TASK_SYSTEM(LIBDISPATCH)\n #include <dispatch/dispatch.h>\n@@ -94,12 +96,12 @@ struct executor_type {\n     using result_type = void;\n \n     template <typename F>\n-    auto operator()(F f) const -> std::enable_if_t<std::is_nothrow_invocable_v<F>> {\n-        using f_t = decltype(f);\n+    auto operator()(F&& f) const -> std::enable_if_t<std::is_nothrow_invocable_v<std::decay_t<F>>> {\n+        using f_t = std::decay_t<F>;\n \n         dispatch_group_async_f(detail::group()._group,\n                                dispatch_get_global_queue(platform_priority(P), 0),\n-                               new f_t(std::move(f)), [](void* f_) {\n+                               new f_t(std::forward<F>(f)), [](void* f_) {\n                                    auto f = static_cast<f_t*>(f_);\n                                    (*f)();\n                                    delete f;\n@@ -161,12 +163,13 @@ class task_system {\n \n     template <typename F>\n     void operator()(F&& f) {\n-        auto work = CreateThreadpoolWork(&callback_impl<F>, new F(std::forward<F>(f)),\n-                                         &_callBackEnvironment);\n+        auto p = std::make_unique<F>(std::forward<F>(f));\n+        auto work = CreateThreadpoolWork(&callback_impl<F>, p.get(), &_callBackEnvironment);\n \n         if (work == nullptr) {\n             throw std::bad_alloc();\n         }\n+        p.release(); // ownership was passed to thread\n         SubmitThreadpoolWork(work);\n     }\n \n@@ -461,12 +464,13 @@ template <executor_priority P = executor_priority::medium>\n struct executor_type {\n     using result_type = void;\n \n-    void operator()(task<void() noexcept>&& f) const {\n+    template <class F>\n+    auto operator()(F&& f) const -> std::enable_if_t<std::is_nothrow_invocable_v<std::decay_t<F>>> {\n         static task_system<P> only_task_system{[] {\n             at_pre_exit([]() noexcept { only_task_system.join(); });\n             return task_system<P>{};\n         }()};\n-        only_task_system(std::move(f));\n+        only_task_system(std::forward<F>(f));\n     }\n };\n \n@@ -476,8 +480,9 @@ template <executor_priority P = executor_priority::medium>\n struct executor_type {\n     using result_type = void;\n \n-    void operator()(task<void() noexcept>&& f) const {\n-        pts().execute<static_cast<std::size_t>(P)>(std::move(f));\n+    template <class F>\n+    auto operator()(F&& f) const -> std::enable_if_t<std::is_nothrow_invocable_v<std::decay_t<F>>> {\n+        pts().execute<static_cast<std::size_t>(P)>(std::forward<F>(f));\n     }\n };\n "},{"sha":"4b223a61be4d1e7bdc412d6c2641f38f305033b4","filename":"stlab/concurrency/future.hpp","status":"modified","additions":14,"deletions":25,"changes":39,"blob_url":"https://github.com/stlab/stlab/blob/facbd553cca8774d9df4fa01ad1d9a832d36eb1e/stlab%2Fconcurrency%2Ffuture.hpp","raw_url":"https://github.com/stlab/stlab/raw/facbd553cca8774d9df4fa01ad1d9a832d36eb1e/stlab%2Fconcurrency%2Ffuture.hpp","contents_url":"https://api.github.com/repos/stlab/stlab/contents/stlab%2Fconcurrency%2Ffuture.hpp?ref=facbd553cca8774d9df4fa01ad1d9a832d36eb1e","patch":"@@ -47,7 +47,6 @@ inline namespace v1 {\n \n enum class future_error_codes { // names for futures errors\n     broken_promise = 1,\n-    reduction_failed,\n     no_state\n };\n \n@@ -64,9 +63,6 @@ inline const char* Future_error_map(\n         case future_error_codes::no_state:\n             return \"no state\";\n \n-        case future_error_codes::reduction_failed:\n-            return \"reduction failed\";\n-\n         default:\n             return nullptr;\n     }\n@@ -246,8 +242,8 @@ struct shared_future {\n template <typename... Args>\n struct shared_task {\n     virtual ~shared_task() = default;\n+\n     virtual void remove_promise() = 0;\n-    virtual void add_promise() = 0;\n \n     virtual void operator()(Args... args) = 0;\n \n@@ -504,24 +500,20 @@ struct shared_base<void> : std::enable_shared_from_this<shared_base<void>> {\n };\n \n template <typename R, typename... Args>\n-struct shared<R(Args...)> : shared_base<R>, shared_task<Args...> {\n+struct shared<R(Args...)> final : shared_base<R>, shared_task<Args...> {\n     using function_t = task<R(Args...)>;\n \n-    std::atomic_size_t _promise_count{1};\n     function_t _f;\n \n     template <typename F>\n     shared(executor_t s, F&& f) : shared_base<R>(std::move(s)), _f(std::forward<F>(f)) {}\n \n     void remove_promise() override {\n-        if ((--_promise_count == 0) && _f) {\n-            this->set_exception(\n-                std::make_exception_ptr(future_error(future_error_codes::broken_promise)));\n-        }\n+        if (!_f) return;\n+        this->set_exception(\n+            std::make_exception_ptr(future_error(future_error_codes::broken_promise)));\n     }\n \n-    void add_promise() override { ++_promise_count; }\n-\n     void operator()(Args... args) noexcept override {\n         if (!_f) return;\n \n@@ -530,6 +522,7 @@ struct shared<R(Args...)> : shared_base<R>, shared_task<Args...> {\n         } catch (...) {\n             this->set_exception(std::current_exception());\n         }\n+\n         _f = function_t();\n     }\n \n@@ -571,14 +564,10 @@ class packaged_task {\n         if (auto p = _p.lock()) p->remove_promise();\n     }\n \n-    packaged_task(const packaged_task& x) : _p(x._p) {\n-        if (auto p = _p.lock()) p->add_promise();\n-    }\n+    packaged_task(const packaged_task&) = delete;\n+    packaged_task& operator=(const packaged_task&) = delete;\n \n     packaged_task(packaged_task&&) noexcept = default;\n-\n-    packaged_task& operator=(const packaged_task& x) { return *this = packaged_task{x}; }\n-\n     packaged_task& operator=(packaged_task&& x) noexcept = default;\n \n     template <typename... A>\n@@ -1182,9 +1171,9 @@ auto apply_when_any_arg(F& f, P& p) {\n }\n \n template <std::size_t i, typename E, typename P, typename T>\n-void attach_when_arg_(E&& executor, std::shared_ptr<P>& p, T a) {\n+void attach_when_arg_(E&& executor, std::shared_ptr<P>& shared, T a) {\n     auto holds =\n-        std::move(a).recover(std::forward<E>(executor), [_w = std::weak_ptr<P>(p)](auto x) {\n+        std::move(a).recover(std::forward<E>(executor), [_w = std::weak_ptr<P>(shared)](auto x) {\n             auto p = _w.lock();\n             if (!p) return;\n \n@@ -1194,8 +1183,8 @@ void attach_when_arg_(E&& executor, std::shared_ptr<P>& p, T a) {\n                 p->template done<i>(std::move(x));\n             }\n         });\n-    std::unique_lock<std::mutex> lock{p->_guard};\n-    p->_holds[i] = std::move(holds);\n+    std::unique_lock<std::mutex> lock{shared->_guard};\n+    shared->_holds[i] = std::move(holds);\n }\n \n template <typename E, typename P, typename... Ts, std::size_t... I>\n@@ -1670,8 +1659,8 @@ auto async(E executor, F&& f, Args&&... args)\n         executor,\n         std::bind<result_type>(\n             [_f = std::forward<F>(f)](\n-                unwrap_reference_t<std::decay_t<Args>>&... args) mutable -> result_type {\n-                return std::move(_f)(move_if<!is_reference_wrapper_v<std::decay_t<Args>>>(args)...);\n+                unwrap_reference_t<std::decay_t<Args>>&... brgs) mutable -> result_type {\n+                return std::move(_f)(move_if<!is_reference_wrapper_v<std::decay_t<Args>>>(brgs)...);\n             },\n             std::forward<Args>(args)...));\n "},{"sha":"8dc156ddb00344f77cd1bee1b81ae0736a2f3d10","filename":"test/CMakeLists.txt","status":"modified","additions":2,"deletions":1,"changes":3,"blob_url":"https://github.com/stlab/stlab/blob/facbd553cca8774d9df4fa01ad1d9a832d36eb1e/test%2FCMakeLists.txt","raw_url":"https://github.com/stlab/stlab/raw/facbd553cca8774d9df4fa01ad1d9a832d36eb1e/test%2FCMakeLists.txt","contents_url":"https://api.github.com/repos/stlab/stlab/contents/test%2FCMakeLists.txt?ref=facbd553cca8774d9df4fa01ad1d9a832d36eb1e","patch":"@@ -48,7 +48,8 @@ add_executable( stlab.test.future\n   future_when_any_range_tests.cpp\n   tuple_algorithm_test.cpp\n   main.cpp\n-  future_test_helper.hpp )\n+  future_test_helper.hpp\n+  future_reduction_tests.cpp)\n \n if( NOT STLAB_NO_STD_COROUTINES )\n   target_sources( stlab.test.future PUBLIC future_coroutine_tests.cpp )"},{"sha":"6972cff99d7e3c6df632d5e847f08bfa95179e2b","filename":"test/future_reduction_tests.cpp","status":"added","additions":25,"deletions":0,"changes":25,"blob_url":"https://github.com/stlab/stlab/blob/facbd553cca8774d9df4fa01ad1d9a832d36eb1e/test%2Ffuture_reduction_tests.cpp","raw_url":"https://github.com/stlab/stlab/raw/facbd553cca8774d9df4fa01ad1d9a832d36eb1e/test%2Ffuture_reduction_tests.cpp","contents_url":"https://api.github.com/repos/stlab/stlab/contents/test%2Ffuture_reduction_tests.cpp?ref=facbd553cca8774d9df4fa01ad1d9a832d36eb1e","patch":"@@ -0,0 +1,25 @@\n+/*\n+    Copyright 2015 Adobe\n+    Distributed under the Boost Software License, Version 1.0.\n+    (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n+*/\n+\n+/**************************************************************************************************/\n+\n+#include <stlab/concurrency/future.hpp>\n+\n+#include <boost/test/unit_test.hpp>\n+\n+#include <stlab/concurrency/utility.hpp>\n+\n+using namespace stlab;\n+\n+BOOST_AUTO_TEST_SUITE(reduction_tests)\n+\n+BOOST_AUTO_TEST_CASE(void_void_reduction) {\n+    auto f = make_ready_future(immediate_executor) |\n+             [] { return make_ready_future(immediate_executor); };\n+    BOOST_REQUIRE(!f.exception());\n+}\n+\n+BOOST_AUTO_TEST_SUITE_END()"}]}