![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
coroutineBoost , Boost.Asio , Reference
|
Имя |
Описание |
---|---|
Построение корутина в его первоначальном состоянии. |
|
Возвращается истинно, если корутина — дитя вилки. |
|
Возвращается истинно, если корутина достигла своего конечного состояния. |
|
Возвращается истинно, если корутина является родителем вилки. |
Класс<coroutine
>может использоваться для реализации безстековых корутин. Сам класс используется для хранения текущего состояния корутина.
Корутины являются копируемыми и присваиваемыми, а пространство над головой представляет собой одну интуицию. Их можно использовать в качестве базового класса:
class session : coroutine { ... };
или в качестве члена данных:
class session { ... coroutine coro_; };
или даже связан в качестве аргумента функции с использованием лямбда или<bind()
>. Важно то, что приложение сохраняет копию объекта до тех пор, пока корутина должна быть сохранена.
Корутин используется в сочетании с определенными «псевдоключевыми словами», которые реализуются как макросы. Эти макросы определяются файлом заголовка:
#include <boost/asio/yield.hpp>
и могут быть не определены следующим образом:
#include <boost/asio/unyield.hpp>
вернуться
Макро<reenter
>используется для определения тела корутина. Для этого требуется один аргумент: указатель или ссылка на корутинный объект. Например, если базовый класс является корутинным объектом, вы можете написать:
reenter (this) { ... coroutine body ... }
Если вы являетесь участником данных или другой переменной, вы можете написать:
reenter (coro_) { ... coroutine body ... }
Когда<reenter
>выполняется во время выполнения, управление переходит к месту последнего<yield
>или<fork
>.
Корутинный орган также может быть единым утверждением, таким как:
reenter (this) for (;;) { ... }
Ограничение:Макрос<reenter
>реализуется с помощью переключателя. Это означает, что вы должны быть осторожны при использовании локальных переменных в организме. Локальная переменная не допускается в положении, когда повторное вхождение в корутин может обойти определение переменной.
доходностьзаявление
Эта форма ключевого слова<yield
>часто используется с асинхронными операциями:
yield socket_->async_read_some(buffer(*buffer_), *this);
Это делится на четыре логических шага:
yield
>сохраняет текущее состояние корутина.Когда асинхронная операция завершается, объект функции вызывается и<reenter
>вызывает передачу управления в точку резюме. Важно помнить о переносе корутинного состояния вперед с асинхронной операцией. В приведенном выше фрагменте текущий класс представляет собой объект функции с корутинным объектом в качестве базового класса или элемента данных.
Утверждение также может быть составным, и это позволяет нам определить локальные переменные с ограниченным охватом:
yield { mutable_buffers_1 b = buffer(*buffer_); socket_->async_read_some(b, *this); }
доходностьвыражение;
Эта форма<yield
>часто используется в генераторах или корутинных парсерах. Например, объект функции:
struct interleave : coroutine { istream& is1; istream& is2; char operator()(char c) { reenter (this) for (;;) { yield return is1.get(); yield return is2.get(); } } };
определяет тривиальный корутин, который переплетает символы из двух входных потоков.
Этот тип<yield
>делится на три логических шага:
yield
>сохраняет текущее состояние корутина.доходность;
Эта форма<yield
>эквивалентна следующим шагам:
yield
>сохраняет текущее состояние корутина.Эта форма может применяться, когда корутины используются для совместной резьбы, а планирование явно управляется. Например:
struct task : coroutine { ... void operator()() { reenter (this) { while (... not finished ...) { ... do something ... yield; ... do some more ... yield; } } } ... }; ... task t1, t2; for (;;) { t1(); t2(); }
разрыв доходности;
Окончательная форма<yield
>используется для явного прекращения корутина. Эта форма состоит из двух этапов:
yield
>устанавливает корутинное состояние для обозначения прекращения.После того, как они были прекращены, призывы к<is_complete()
>возвращению истинны, и корутина не может быть возвращена.
Обратите внимание, что корутин также может быть неявно прекращен, если корутинное тело выходит без выхода, например, путем возврата, броска или бега к концу тела.
вилказаявление
Псевдоключевое слово<fork
>используется при «разветвлении» корутина, т.е. разбиении его на две (или более) копии. Одно из применений<fork
>находится на сервере, где для обработки каждого клиентского соединения создается новый корутин:
reenter (this) { do { socket_.reset(new tcp::socket(io_service_)); yield acceptor->async_accept(*socket_, *this); fork server(*this)(); } while (is_parent()); ... client-specific handling follows ... }
Логические этапы, участвующие в<fork
>:
fork
>сохраняет текущее состояние корутина.Функции<is_parent()
>и<is_child()
>могут использоваться для различения между родителем и ребенком. Вы будете использовать эти функции для изменения последующего потока управления.
Обратите внимание, что<fork
>не делает сам разветвление. В обязанности приложения входит создание клона корутина и его вызов. Клон можно вызвать немедленно, как указано выше, или запланировать на отсроченное исполнение, используя что-то вроде<io_service::post()
>.
При желании приложение может использовать макро-имена, которые следуют более типичному соглашению об именах, а не псевдоключевым словам. Это:
BOOST_ASIO_CORO_REENTER
>вместо<reenter
>BOOST_ASIO_CORO_YIELD
>вместо<yield
>BOOST_ASIO_CORO_FORK
>вместо<fork
>Заголовок:<boost/asio/coroutine.hpp
>
Удобный заголовок:<boost/asio.hpp
>
Статья coroutine раздела Boost.Asio Reference может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.
реклама |