NVIDIA / stdexec

`std::execution`, the proposed C++ framework for asynchronous and parallel programming.
Apache License 2.0
1.56k stars 159 forks source link

stop_token is not propagated into exec::task #973

Closed GorNishanov closed 1 year ago

GorNishanov commented 1 year ago

Repro:

#include <exec/async_scope.hpp>
#include <exec/static_thread_pool.hpp>
#include <exec/task.hpp>
#include <iostream>
#include <stdexec/execution.hpp>

exec::task<void> coro() {
  auto stop_token = co_await stdexec::get_stop_token();
  std::cout << "stop possible: " << stop_token.stop_possible() << "\n";
}

int main() {
  exec::static_thread_pool pool(1);
  exec::async_scope scope;
  scope.spawn(stdexec::on(pool.get_scheduler(), coro()));
  stdexec::sync_wait(scope.on_empty());
}

Equivalent code in libunifex works.

It seems that:

      template <__scheduler_affinity _Affinity, __indirect_stop_token_provider _ParentPromise>
      explicit __default_awaiter_context(
        __default_task_context_impl<_Affinity>& __self,
        _ParentPromise& __parent) {
        if constexpr (_Affinity == __scheduler_affinity::__sticky) {
          __check_parent_promise_has_scheduler<_ParentPromise>();
          __self.__scheduler_ = get_scheduler(get_env(__parent));
        }
        // Register a callback that will request stop on this basic_task's
        // stop_source when stop is requested on the parent coroutine's stop
        // token.
        using __stop_token_t = stop_token_of_t< env_of_t<_ParentPromise>>;
        using __stop_callback_t =
          typename __stop_token_t::template callback_type<__forward_stop_request>;

        if constexpr (std::same_as<__stop_token_t, in_place_stop_token>) {
          __self.__stop_token_ = get_stop_token(get_env(__parent));
// -------------------vvv here we are getting never_stop_token token
        } else if (auto __token = get_stop_token(get_env(__parent)); __token.stop_possible()) {
          __stop_callback_.emplace<__stop_callback_t>(
            std::move(__token), __forward_stop_request{__stop_source_});
          __self.__stop_token_ = __stop_source_.get_token();
        }
      }

      in_place_stop_source __stop_source_{};
      std::any __stop_callback_{};
    };
ericniebler commented 1 year ago

Fixed by #974. Thanks for the report, Gor!