Naios / continuable

C++14 asynchronous allocation aware futures (supporting then, exception handling, coroutines and connections)
https://naios.github.io/continuable/
MIT License
815 stars 44 forks source link

boost::beast::ssl_stream::async_handshake() doesn't accept cti::use_continuable #52

Open Spongman opened 1 year ago

Spongman commented 1 year ago

@Naios

boost::beast::ssl_stream<boost::beast::tcp_stream>* stream;
const auto f = stream->async_handshake(boost::asio::ssl::stream_base::client, boost::asio::use_future); // compiles
const auto g = stream->async_handshake(boost::asio::ssl::stream_base::client, cti::use_continuable); // error
---
error: no matching function for call to 'boost::beast::ssl_stream<boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::any_io_executor, boost::beast::unlimited_rate_policy> >::async_handshake(boost::asio::ssl::stream_base::handshake_type, const cti::use_continuable_t<>&)'
  143 |    const auto g = stream->async_handshake(boost::asio::ssl::stream_base::client, cti::use_continuable);

it works fine with other boost & beast APIs.

Commit Hash

6bffb44d2bcca4989945e4d76ce8d35cf8cdcebd (4.1.0 release)

Spongman commented 1 year ago

I notice that the deduction for async_handshake is different than that for, say, async_connect

    template<class HandshakeHandler>
    BOOST_ASIO_INITFN_RESULT_TYPE(HandshakeHandler, void(boost::system::error_code))
    async_handshake(handshake_type type,
        BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler)

vs.

template <typename Protocol, typename Executor, typename Iterator,
    BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
      Iterator)) IteratorConnectHandler>
inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,
    void (boost::system::error_code, Iterator))
async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end,
    BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler)

that's all a little beyond me.

that doesn't explain, however, why it works for use_future and not use_continuable.

Naios commented 1 year ago

Thank your for your report. I was able to reproduce this issue (on boost 1.80). I'm not entirely sure yet, what is causing this.

Naios commented 1 year ago

I found the reason for this issue:

Since boost:::asio 1.72 or asio (standalone) 1.16 the async_result trait used for creating the promise type does not require a fixed type anymore. Before that we had to return a fixed type independent of the promise initiation. This makes it possible to return a non-allocating continuable that depends on the promise Initiation.

See

template <typename Signature, typename Matcher>
class async_result<cti::use_continuable_t<Matcher>, Signature> {
public:
#if defined(CTI_DETAIL_ASIO_HAS_EXPLICIT_RET_TYPE_INTEGRATION)
  using return_type = typename cti::detail::asio::initiate_make_continuable<
      Signature>::erased_return_type;
#endif

The async_handshake method uses BOOST_ASIO_INITFN_RESULT_TYPE for deducing the promise type. As far as I know this should be replaced with BOOST_ASIO_INITFN_AUTO_RESULT_TYPE to auto-deduce the result. Asio only keeps the old explicit define for backwards compatibility: https://github.com/boostorg/asio/search?q=BOOST_ASIO_INITFN_RESULT_TYPE .

I would suggest that you ask at boostorg/beast whether they can auto-replace BOOST_ASIO_INITFN_RESULT_TYPE by BOOST_ASIO_INITFN_AUTO_RESULT_TYPE or if there is a reason why they are still using the old define. If this is not possible I might consider implementing an alternative token.

As workaround you can temporarily define CTI_DETAIL_ASIO_HAS_EXPLICIT_RET_TYPE_INTEGRATION that enables the asyn_result<>::return_type, but this leads to performance disadvantages.


For reference see:

https://github.com/Naios/continuable/blob/b51be39e7126c397cec9d13fefdfa3cbbe8291f0/include/continuable/external/asio.hpp#L149-L175

uohmak4fvpqe commented 1 year ago

I am having seemingly the same issue, both with async_connect and (ssl) async_handshake. I am prone to ask the beast guys if you need me to do it but isn't that possible that you do it instead as you probably know better how tell them propery ?