Boost Asio Asyn c Состояние гонки подключений? - PullRequest
1 голос
/ 02 августа 2020

Я смотрю на пример Boost Asio Blocking TCP Client timeout с особым интересом к тому, как реализованы тайм-ауты соединения. Как мы узнаем из документации, что обработчик обратного вызова и последующие проверки не вызывают состояния гонки?

Команда асинхронного соединения

boost::asio::async_connect(socket_, iter, var(ec) = _1);

выполняет var(ec) = _1, который является обработчиком для установки кода ошибки после выполнения. В качестве альтернативы здесь можно использовать полную и явную лямбду.

В то же время функция check_deadline, похоже, вызывается членом deadline_. Тайм-аут, по-видимому, обеспечивается принудительным закрытием сокета в течение крайнего срока, после чего мы предполагаем, что, возможно, вернется блокирующий оператор

do io_service_.run_one(); while (ec == boost::asio::error::would_block);

. Сначала я подумал, что код ошибки должен быть atomi c, но похоже, что это не так. Вместо этого эта страница , по-видимому, указывает на то, что модель цепочки будет работать всякий раз, когда вызовы сокета / контекста поступают из одного и того же потока.

Таким образом, мы предполагаем, что каждый обратный вызов для крайнего срока ( который находится в Asio), а дескриптор подпрограммы async_connect не будет выполняться одновременно. Такие страницы, как this в документации, намекают, что обработчики будут выполняться только во время run() вызовов, что предотвратит выполнение команды while(ec == whatever) сзади, когда обработчик в настоящее время изменяет свое значение.

Как я знаю это явно? Что в документации прямо говорит мне, что никакие обработчики никогда не будут выполняться вне этих подпрограмм? Если это правда, страница в шаблоне проектирования проактора должна предполагать это, но никогда явно, где «Инициатор» ведет к «Обработчику завершения».

Я обнаружил закрытие документация для io_context говоря

Синхронные операции с объектами ввода-вывода неявно запускают объект io_context для отдельной операции. Функции io_context run (), run_one (), run_for (), run_until (), poll () или poll_one () должны вызываться для того, чтобы io_context выполнял асинхронные операции от имени программы C ++. Уведомление о завершении асинхронной операции доставляется путем вызова связанного обработчика. Обработчики вызываются только потоком, который в настоящее время вызывает любую перегрузку run (), run_one (), run_for (), run_until (), poll () или poll_one () для io_context.

Это означает, что если у меня есть один поток, выполняющий команду run_one(), то его путь управления будет ждать, пока не станет доступен обработчик, и, в конечном итоге, пройдет через обработчик, после чего он вернется и проверит значение ec.

Правильно ли это, и это «Обработчики вызываются только потоком, который в настоящее время вызывает любую перегрузку run (), run_one (), run_for (), run_until (), poll () или poll_one () для io_context». Лучшее утверждение для понимания того, как код всегда будет работать? Есть ли другая экспозиция?

1 Ответ

1 голос
/ 02 августа 2020

Библиотека Asio готовится к стандартизации как NetworkingTS. Эта часть действительно является сделкой:

Обработчики вызываются только потоком, который в настоящее время вызывает любую перегрузку run (), run_one (), run_for (), run_until (), poll () или poll_one () для io_context

Вы правы, заключив, что весь пример на 100% однопоточный¹. Не может быть гонки.

Я лично считаю, что лучший ресурс - это Threads and Boost.Asio page:

  • Просто вызывая io_context: : run () из одного потока, код пользователя может избежать сложности разработки, связанной с синхронизацией. Например, пользователь библиотеки может реализовать масштабируемые серверы, которые являются однопоточными (с точки зрения пользователя).

Это также повторяет истину, высказанную ранее:

[...] следующая гарантия:

  • Обработчики асинхронного завершения будут вызываться только из потоков, которые в данный момент вызывают io_context :: run ().

¹ кроме потенциальных внутренних потоков службы в зависимости от платформы / расширений, например потоков подробностей страницы

...