Skip to content

Don't type-erase the CompletionHandler #3

@vinniefalco

Description

@vinniefalco

This code is incorrect:

    boost::asio::async_completion<CompletionToken, write_signature> c(token);
    do_write(std::move(c.completion_handler));

The problem is that do_write receives the handler as a std::function, which type-erases the handler. Later on, you call boost::asio::post with this object. Since the function object is typed-erased, it loses the associated allocator and more importantly the associated executor. The consequence is that when a user writes:

  auto const bytes_transferred =
    utp_sock.async_write_some(
      buffers,
      boost::asio::bind_executor(strand_, my_handler));

The wrapper returned by bind_executor loses its type information when it is stored in a function object. Then later on when you call post, it doesn't go through the strand.

This is going to sound painful, but if you want your library to work nicely with Networking TS / Asio (and I think you have really nice library here, so you should want this) then you are going to have to do the following:

  • Remove all use of std::function (and never use it again)
  • Move everything in the .cpp files into header files (this library must be header-only to work right)
  • Rewrite your asynchronous operations (connect, read some, write some) as composed operations

These tutorials should help:
https://www.boost.org/doc/libs/1_69_0/libs/beast/doc/html/beast/using_io/writing_composed_operations.html
https://www.boost.org/doc/libs/1_69_0/libs/beast/doc/html/beast/using_io/example_detect_ssl.html

You might also consider studying the implementation of asio and beast. I can help with that by offering pointers and answering questions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions