![]()  | 
![]() ![]() ![]() ![]()  | 
![]()  | 
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.
реклама  |