Почему boost :: asio :: ip :: tcp :: basic_stream_socket :: available имеет длительное время выполнения? - PullRequest
1 голос
/ 25 мая 2020

Для выполнения метода boost::asio::ip::tcp::basic_stream_socket::available требуется около 3 мкс. Это время не слишком медленное, но все же медленнее, чем я ожидал бы для вызова метода, который просто возвращает состояние. В чем причина того, что это занимает так много времени? Есть ли там замки? Если да, неужели несколько параллельных вызовов блокируют конкуренцию друг с другом?

1 Ответ

0 голосов
/ 26 мая 2020

Я бы сказал, что это не имеет большого значения. Чтобы напрямую ответить на вопрос, вот что делается для реализации реактивных сокетов (например, Linux), предварительно обработанных и переформатированных:

size_t available(socket_type s, boost::system::error_code& ec) {
    if (s == invalid_socket) {
        ec = boost::asio::error::bad_descriptor;
        return 0;
    }
    ioctl_arg_type value = 0;
    int result = error_wrapper(::ioctl(s, FIONREAD, &value), ec);
    if (result == 0)
        ec = boost::system::error_code();
    return ec ? static_cast<size_t>(0) : static_cast<size_t>(value);
}

Как видите, все это должно быть встроено в прямой FIONREAD ioctl, исключая условия ошибки. Это довольно скудно и не займет меньше времени, если вы сделаете это напрямую, на случай, если вы захотите проверить:

static inline size_t my_available(boost::asio::ip::tcp::socket& socket, boost::system::error_code& ec) {
    auto s = socket.native_handle();
    if (s == -1) {
        ec = boost::asio::error::bad_descriptor;
        return 0;
    }
    int value = 0;
    if (auto err = ::ioctl(s, FIONREAD, &value))
        ec = boost::system::error_code(err, boost::asio::error::get_system_category());
    else
        ec = boost::system::error_code();
    return ec? value : 0;
}

Операции в стиле Reactor

Если хотите чтобы дождаться, пока данные станут доступны и действовать при первой возможности, тогда вы можете async_wait на сокете: https://www.boost.org/doc/libs/1_73_0/doc/html/boost_asio/reference/basic_stream_socket/async_wait.html

Вы можете указать ожидание доступности чтения / записи, или при наличии состояния ожидающей ошибки

Документы: https://www.boost.org/doc/libs/1_73_0/doc/html/boost_asio/overview/core/reactor.html

...