asio icon indicating copy to clipboard operation
asio copied to clipboard

cancellation_signal for co_spawn with use_future

Open battlmonstr opened this issue 3 years ago • 0 comments

I'm trying to bootstrap a coroutine task from a non-coroutine context, and be able to stop it from outside via a cancellation_signal:

struct Task {
  void start(awaitable run);
  void stop();
  boost::asio::cancellation_signal signal;
}

Task::start(awaitable run) {
  auto cancellable_completion = boost::asio::bind_cancellation_slot(signal.slot(), MY_COMPLETION);
  auto task = boost::asio::co_spawn(io_context, run, cancellable_completion);
  // ...
}

Task::stop() {
  signal.emit(boost::asio::cancellation_type::all);
}

In the docs it says that the bind_xxx functions adapt a completion token to have a desired associated characteristic, so I expect to pass any completion token in place of MY_COMPLETION.

Yet I've found that passing use_future doesn't compile:

  // variant 1
  auto cancellable_completion = boost::asio::bind_cancellation_slot(signal.slot(), use_future);

Note that passing a callback or use_awaitable works fine:

  // variant 2
  auto cancellable_completion = boost::asio::bind_cancellation_slot(signal.slot(), [](std::exception_ptr) {});

  // variant 3
  auto cancellable_completion = boost::asio::bind_cancellation_slot(signal.slot(), use_awaitable);

I wish the future worked too, so that I could bridge it with future-based code, and be able to .wait().

Errors with use_future:


.../include/boost/asio/bind_cancellation_slot.hpp:623:34: error: no member named 'initiate' in 'boost::asio::async_result<boost::asio::use_future_t<>, void (std::exception_ptr)>'
    (async_result<T, Signature>::initiate(
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
.../include/boost/asio/async_result.hpp:820:12: note: expanded from macro 'BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE'
  decltype expr
           ^~~~
.../include/boost/asio/async_result.hpp:710:5: note: in instantiation of template class 'boost::asio::async_result<boost::asio::cancellation_slot_binder<boost::asio::use_future_t<>, boost::asio::cancellation_slot>, void (std::exception_ptr)>' requested here
  : T, async_result_memfns_base
    ^
.../include/boost/asio/async_result.hpp:726:8: note: in instantiation of template class 'boost::asio::detail::async_result_memfns_derived<boost::asio::async_result<boost::asio::cancellation_slot_binder<boost::asio::use_future_t<>, boost::asio::cancellation_slot>, void (std::exception_ptr)>>' requested here
      &async_result_memfns_derived<T>::initiate>*);
       ^
.../include/boost/asio/async_result.hpp:730:36: note: while substituting explicitly-specified template arguments into function template 'async_result_initiate_memfn_helper' 
  : integral_constant<bool, sizeof(async_result_initiate_memfn_helper<
                                   ^
.../include/boost/asio/async_result.hpp:871:14: note: in instantiation of template class 'boost::asio::detail::async_result_has_initiate_memfn<boost::asio::cancellation_slot_binder<boost::asio::use_future_t<>, boost::asio::cancellation_slot> &, void (std::exception_ptr)>' requested here
    !detail::async_result_has_initiate_memfn<
             ^
.../include/boost/asio/async_result.hpp:1180:5: note: while substituting deduced template arguments into function template 'async_initiate' [with CompletionToken = boost::asio::cancellation_slot_binder<boost::asio::use_future_t<>, boost::asio::cancellation_slot> &, Signatures = (no value), Initiation = boost::asio::detail::initiation_archetype<void (std::exception_ptr)>, Args = <>]
    async_initiate<T, Signatures...>(
    ^
.../include/boost/asio/async_result.hpp:1180:5: note: (skipping 1 context in backtrace; use -ftemplate-backtrace-limit=0 to see all)
.../include/boost/asio/async_result.hpp:1178:3: note: while substituting template arguments into constraint expression here
  requires(T&& t)
  ^~~~~~~~~~~~~~~
.../include/boost/asio/impl/co_spawn.hpp:296:5: note: while checking the satisfaction of concept 'completion_token_for<boost::asio::cancellation_slot_binder<boost::asio::use_future_t<>, boost::asio::cancellation_slot> &, void (std::exception_ptr)>' requested here
    BOOST_ASIO_COMPLETION_TOKEN_FOR(
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.../include/boost/asio/async_result.hpp:1185:3: note: expanded from macro 'BOOST_ASIO_COMPLETION_TOKEN_FOR'
  ::boost::asio::completion_token_for<sig>
  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.../include/boost/asio/impl/co_spawn.hpp:296:5: note: while substituting template arguments into constraint expression here
    BOOST_ASIO_COMPLETION_TOKEN_FOR(
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.../include/boost/asio/async_result.hpp:1185:18: note: expanded from macro 'BOOST_ASIO_COMPLETION_TOKEN_FOR'
  ::boost::asio::completion_token_for<sig>
                 ^~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:104:14: note: while checking constraint satisfaction for template 'co_spawn<boost::asio::io_context, boost::asio::any_io_executor, boost::asio::cancellation_slot_binder<boost::asio::use_future_t<>, boost::asio::cancellation_slot> &>' required here
    auto f = boost::asio::co_spawn(
             ^~~~~
main:104:14: note: in instantiation of function template specialization 'boost::asio::co_spawn<boost::asio::io_context, boost::asio::any_io_executor, boost::asio::cancellation_slot_binder<boost::asio::use_future_t<>, boost::asio::cancellation_slot> &>' requested here
In file included from main.cpp:21:
In file included from .../include/boost/asio/co_spawn.hpp:22:
In file included from .../include/boost/asio/awaitable.hpp:28:
In file included from .../include/boost/asio/any_io_executor.hpp:23:
In file included from .../include/boost/asio/execution_context.hpp:409:
In file included from .../include/boost/asio/impl/execution_context.hpp:18:
In file included from .../include/boost/asio/detail/handler_type_requirements.hpp:53:
.../include/boost/asio/async_result.hpp:663:7: error: no matching constructor for initialization of 'async_result<typename decay<cancellation_slot_binder<use_future_t<>, cancellation_slot> &>::type, void (std::exception_ptr)>' (aka 'async_result<boost::asio::cancellation_slot_binder<boost::asio::use_future_t<>, boost::asio::cancellation_slot>, void (std::exception_ptr)>')
      result(completion_handler)
      ^      ~~~~~~~~~~~~~~~~~~
.../include/boost/asio/async_result.hpp:878:52: note: in instantiation of member function 'boost::asio::async_completion<boost::asio::cancellation_slot_binder<boost::asio::use_future_t<>, boost::asio::cancellation_slot> &, void (std::exception_ptr)>::async_completion' requested here
  async_completion<CompletionToken, Signatures...> completion(token);
                                                   ^
.../include/boost/asio/impl/co_spawn.hpp:272:10: note: in instantiation of function template specialization 'boost::asio::async_initiate<boost::asio::cancellation_slot_binder<boost::asio::use_future_t<>, boost::asio::cancellation_slot> &, void (std::exception_ptr), boost::asio::detail::initiate_co_spawn<boost::asio::any_io_executor>, boost::asio::detail::awaitable_as_function<void, boost::asio::any_io_executor>>' requested here
  return async_initiate<CompletionToken, void(std::exception_ptr)>(
         ^
.../include/boost/asio/bind_cancellation_slot.hpp:517:12: note: candidate constructor not viable: no known conversion from 'typename conditional<is_same<cancellation_slot_binder<use_future_t<>, cancellation_slot> &, completion_handler_type>::value, completion_handler_type &, completion_handler_type>::type' (aka 'boost::asio::cancellation_slot_binder<boost::asio::detail::promise_handler<void (std::exception_ptr), std::allocator<void>>, boost::asio::cancellation_slot>') to 'cancellation_slot_binder<boost::asio::use_future_t<>, boost::asio::cancellation_slot> &' for 1st argument
  explicit async_result(cancellation_slot_binder<T, CancellationSlot>& b)
           ^
.../include/boost/asio/bind_cancellation_slot.hpp:681:3: note: candidate constructor not viable: no known conversion from 'typename conditional<is_same<cancellation_slot_binder<use_future_t<>, cancellation_slot> &, completion_handler_type>::value, completion_handler_type &, completion_handler_type>::type' (aka 'boost::asio::cancellation_slot_binder<boost::asio::detail::promise_handler<void (std::exception_ptr), std::allocator<void>>, boost::asio::cancellation_slot>') to 'const boost::asio::async_result<boost::asio::cancellation_slot_binder<boost::asio::use_future_t<>, boost::asio::cancellation_slot>, void (std::exception_ptr)>' for 1st argument
  async_result(const async_result&) BOOST_ASIO_DELETED;
  ^

I'm using asio from boost 1.78. Compiling using Apple clang version 13.1.6 (clang-1316.0.21.2) from Xcode 13 on macOS 12.4.

battlmonstr avatar Jul 22 '22 14:07 battlmonstr