- when_any
- when_any,
simple completion
- when_any,
return value
- when_any,
produce first outcome, whether result or exception
- when_any,
produce first success
- when_any,
heterogeneous types
- when_any,
a dubious alternative
- when_all functionality
- when_all,
simple completion
- when_all,
return values
- when_all
until first exception
- wait_all,
collecting all exceptions
- when_all,
heterogeneous types
Немного мудрости с первых дней вычислений все еще актуальна сегодня: предпочитайте моделировать состояние программы с помощью указателя команд, а не с булевыми флагами. Другими словами, если программа должнаи #8220;сделать что-тои #8221;, а затем сделать что-то почти то же самое, но с незначительными изменениями... возможно, части этого чего-то должны быть разбиты как более мелкие отдельные функции, а не вводить флаги для изменения внутреннего поведения монолитной функции.
К этому мы бы добавили: предпочли описать поток управления с использованием нативных конструкций C++, таких как вызовы функций<if
>,<while
>,<for
>,<do
>и др. Вместо того, чтобы быть цепочкой обратных вызовов.
Одной из сильных сторонBoost.Fiberявляется гибкость, которую он предоставляет программисту для реструктуризации приложения от цепочек обратного вызова до простой последовательности утверждений на C++, даже когда код в этом волокне фактически переплетается с кодом, работающим в других волокнах.
В последнее время было много дискуссий о преимуществах функции When_any и When_all. При работе с асинхронными и, возможно, ненадежными сервисами, это ценные идиомы. Но, конечно, когда и когда все тесно связаны с использованием цепочек обратного вызова.
В этом разделе представлены рецепты достижения тех же целей в контексте волокна, которое хочет& #8220;сделать что-то& #8221;, когда одна или несколько других независимых мероприятий завершены. Таким образом, это<wait_something()
>функции, а не<when_something()
>функции. Ожидание состоит в том, что вызывающее волокно просит запустить эти независимые действия, затем ждет их, а затем последовательно переходит к любой обработке, зависящей от этих результатов.
Показанные имена функций (например,<wait_first_simple()
>) предназначены только для иллюстративных целей, поскольку все эти функции были объединены в один исходный файл. Предположительно, если (скажем)<wait_first_success()
>наилучшим образом соответствует вашим потребностям в приложении, вы можете ввести этот вариант с именем<wait_any()
>.
![[Note]](/img/note.png) | Note |
---|
Функции, представленные в этом разделе, принимают вариадные списки аргументов задач. Соответствующие<wait_something() >функции, принимающие контейнер задач, оставляют в качестве упражнения для заинтересованного читателя. На самом деле они должны быть проще. Большая часть сложности возникает из-за перегрузки одного и того же имени для обеих целей. |
Весь исходный код этого раздела находится вwait_stuff.cpp.
Мы нашли удобным смоделировать асинхронную задачу с помощью этой функции:
template< typename T >
T sleeper_impl( T item, int ms, bool thrw = false) {
std::ostringstream descb, funcb;
descb << item;
std::string desc( descb.str() );
funcb << " sleeper(" << item << ")";
Verbose v( funcb.str() );
boost::this_fiber::sleep_for( std::chrono::milliseconds( ms) );
if ( thrw) {
throw std::runtime_error( desc);
}
return item;
}
<sleeper()
>& #8220;передние концы& #8221;для<std::string
>,<double
>и<int
>.
<Verbose
>просто печатает сообщение<std::cout
>о строительстве и разрушении.
В основном:
- <
sleeper()
>печатает начальное сообщение; - спит за указанное количество миллисекунд;
- Если<
thrw
>пропущено как<true
>, бросает строку описания пройденного<item
>; - Вернется обратно (44).
- На выходе<
sleeper()
>выдает стоп-сообщение.
Эта функция будет включать в пример вызовы к различным функциям, представленным ниже.