chriskohlhoff / asio

Asio C++ Library
http://think-async.com/Asio
4.85k stars 1.2k forks source link

channel::close() is immediate, ignoring pending messages in the channel #1236

Open madmongo1 opened 1 year ago

madmongo1 commented 1 year ago

Please consider this simple producer:

asio::awaitable< void >
producer(asio::experimental::channel< void(error_code, std::string) > &chan)
{
    for (int i = 1; i <= 100; ++i)
    {
        auto str = fmt::format("message {}", i);
        if (!chan.try_send(error_code(), str))
            co_await chan.async_send(
                error_code(), std::move(str), asio::deferred);
    }
    // this is a proxy for an async_close
    if (!chan.try_send(error_code(asio::error::eof), std::string()))
        co_await chan.async_send(
            error_code(asio::error::eof), std::string(), asio::deferred);
    //    chan.close();
}

If the explicit async_send of the error is removed and the chan.close() is uncommented, then the consumer will miss messages produced by this producer. In my test case I initialised the channel with a buffer space of 100 messages. In that case, the consumer didn't receive any messages. It seems to me that it would be more correct either:

  1. modify close() so that it inserts a marker into the internal queue to close after the most recent sent message, or
  2. add an async_close() method, or
  3. add an async_flush() method

2 & 3 would allow the producer to coincide the closure of the channel with the consumption of the last message sent prior to the close.