2016-02-29 5 views
1

Im просмотр функции asio use_future, чтение source code.asio :: use_future и цикл событий

Но не могу понять, как это работает. Скажем, если я называть

auto fut = async_write(sock, buffer, use_future) 

fut становится std::future (в соответствии с исходным кодом). Теперь, если я звоню fut.get(), я должен ждать завершения операции async и получить возвращаемое значение. В use_future.hpp файл я вижу стандарт ASIO async_result разрешения обработчика и так далее ..

Но если я блокировать на future::get() вызова, как петля IO продолжать работать так, операцию можно выполнить? Создает ли системный поток?

ответ

3

Asio tutorial упоминает, что для однопоточных приложений, можно наблюдать плохую отзывчивость, если обработчики принимать долгое время для завершения. В этом случае, если только один поток обрабатывает io_service, тогда можно будет наблюдать тупик.

Когда boost::asio::use_future используется, инициирующий операция:

  • инициирует основную работу с обработчиком завершения, который установит значение или ошибку на std::promise
  • вернуться на вызывающий абонент A std::future связанного с std::promise.

Если один поток обработки услуги ввода/вывода, и он блокирует на future::get(), то обработчик завершения, который установил бы std::promise никогда не будет вызываться. Обязанностью приложения является предотвращение этого. official futures example выполняет это путем создания дополнительного потока, который предназначен для обработки услуги ввода-вывода и ждет std::future из потока, который не обрабатывает службу ввода-вывода.

// We run the io_service off in its own thread so that it operates 
// completely asynchronously with respect to the rest of the program. 
boost::asio::io_service io_service; 
boost::asio::io_service::work work(io_service); 
std::thread thread([&io_service](){ io_service.run(); }); 

std::future<std::size_t> send_length = 
    socket.async_send_to(..., boost::asio::use_future); 

// Do other things here while the send completes. 

send_length.get(); // Blocks until the send is complete. Throws any errors. 
+0

Это имеет смысл. Но что, если 'use_future' используется внутри обработчиков, вызванных' io_service :: run'? Это снова затормозит. Кажется, эта функция не так безопасна, как кажется. = ( – PSIAlt

+1

@PSIAlt Функции вызова, которые могут бесконечно блокироваться изнутри обработчиков, редко бывают безопасными. Когда я использую 'use_future', я использую его только из потоков, которые не обрабатывают службу ввода-вывода , и все асинхронные операции, которые инициируют эти потоки, используют 'use_future'. В этом подходе нет обработчиков пользователей, в которых могут выполняться блокирующие вызовы. –

+0

, но это также означает, что вы должны использовать поток для каждого соединения, чтобы этот шаблон работал.Я лучше придерживаюсь yield_context вместо этого, он кажется более расширяемым. – PSIAlt

1

Создает ли системную нить?

No. Вы должен бесплатно решить, на какой нить (ы) для запуска io_service::run

+1

[Platform-Specific Notes реализации] В (http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/overview/implementation.html) перечислены все внутренние потоки. Это [demo] (http://coliru.stacked-crooked.com/a/d85347255e8d84dd) показывает, что даже если операция ОС завершается, если 'io_service' не обрабатывается, то обещание никогда не будет выполнено. –

+0

Итак, вопрос: если у меня есть только 1 поток и его блокировка в вызове 'future :: get', где' io_service :: run' обрабатывается для вызова 'prom_handler'? – PSIAlt

Смежные вопросы