Подтвердить что ты не робот

Какие прецеденты для сопрограммы?

Концепция coroutine звучит очень интересно, но я не знаю, если она имеет смысл в реальной продуктивной среде? Каковы прецеденты для сопрограмм, которые могут быть решены более элегантно, проще или эффективнее, чем с другими методами?

4b9b3361

Ответ 1

Истинные сопрограммы требуют поддержки от вашего инструментария - они должны быть реализованы компилятором и поддерживаться базовой структурой.

Один реальный пример Coroutines найден с ключевым словом "yield return", представленным на С# 2.0, который позволяет вам написать метод, который возвращает несколько значений для цикла.

"Возврат доходности" имеет ограничения, однако - реализация использует вспомогательный класс для захвата состояния и поддерживает только конкретный случай сопрограммы в качестве генератора (итератора).

В более общем случае преимущество Coroutines заключается в том, что они делают определенные вычисления на основе состояний намного проще для выражения и легче понять - реализация конечного автомата в виде набора сопрограмм может быть более элегантной, чем более общие подходы. Но для этого требуется поддержка и инструменты, которые еще не существуют на С# или Java.

Ответ 2

Некоторые хорошие ответы, описывающие, что такое сопрограммы.

Но для фактического использования. Возьмите веб-сервер. Он имеет несколько одновременных соединений, и он хочет запланировать чтение и запись всех из них.

Это может быть реализовано с помощью сопрограмм. Каждое соединение представляет собой сопрограмму, которая считывает/записывает небольшой объем данных, а затем "выводит" управление планировщику, который переходит к следующей сопрограмме (что делает то же самое), когда мы перебираем все доступные соединения.

Ответ 3

Многие из них, например:

grep TODO *.c *.h | wc -l

Конвейер выше - это точно сопрограмма: команда grep генерирует последовательность строк, которые идут в буфер, команда wc "ест их"; если буфер заполняется, grep "блокирует" до тех пор, пока буфер не опустеет, и если буфер пуст, команда wc ждет нового ввода.

Дело в том, что они чаще всего используются либо в более ограниченных шаблонах, как упомянутые генераторы Python, так и в качестве конвейеров.

Если вы хотите больше посмотреть на них, см. статьи в Википедии, особенно на сопрограммы и итераторы.

Ответ 4

Я знаю, что это почти 5 лет с тех пор, как был задан вопрос, но я удивлен, что никто не упомянул об использовании игр, в которых сопрограммы часто используются, чтобы существенно сократить время вычисления.

Чтобы поддерживать согласованную частоту кадров в игре, скажем 60 кадров в секунду, у вас есть около 16,6 мс для выполнения кода в каждом кадре. Это включает физическое моделирование, обработку ввода, рисование/роспись.

Давайте скажем, что ваш метод выполняется в каждом кадре. Если ваш метод занимает много времени и заканчивается тем, что он охватывает несколько фреймов, вы собираетесь пошатнуть оставшуюся часть вычисления в игровом цикле, в результате чего пользователь увидит "jank".

Какие сопроводительные материалы позволят вам сделать это, так или иначе, вырезайте это вычисление так, чтобы оно выполнялось немного в каждом кадре.

Чтобы это произошло, сопрограммы по существу позволяют методу "вернуть" вычисление обратно "вызывающему" (в данном случае игровому циклу), чтобы при следующем вызове метода он возобновлялся с того места, где он был остановлен.

Ответ 5

Coroutines полезны для реализации шаблонов производителя/потребителя.

Например, Python представил сопрограммы в языковой функции, называемой generators, которая была предназначена для упрощения реализации итераторов.

Они также могут быть полезны для реализации совместной многозадачности, где каждая задача представляет собой сопрограмму, которая дает планировщик/реактор.

Ответ 6

Coroutines может быть полезна всякий раз, когда система имеет два или более фрагмента кода, наиболее естественным из которых является последовательный ряд шагов, которые предполагают много ожиданий.

Например, рассмотрите устройство, в котором есть пользовательский интерфейс с ЖК-экраном и клавиатурой, и модем, и ему необходимо использовать модем для периодического вызова и отчета о его состоянии независимо от того, что делает пользователь на клавиатуре. Самый приятный способ написать пользовательский интерфейс может заключаться в использовании таких функций, как "input_numeric_value (& CONV_SPEED_FORMAT, & transportor_speed)"; который будет возвращен, когда пользователь введет значение, и наиболее приятным способом обработки сообщения могут быть такие функции, как "wait_for_carrier()"; который вернется, когда устройство либо подключится, либо не решит, что он не будет.

Без сопроцессов подсистема UI или подсистема модема должна быть реализована с использованием конечного автомата. Использование сопрограмм позволяет записывать обе подсистемы в самом естественном стиле. Обратите внимание, что важно, чтобы ни одна из подсистем никогда не заходила очень долго, не вставляя вещи в "последовательное" состояние и не вызывая yield(), и не называет yield(), не вставляя вещи в "последовательное" состояние сначала, но обычно не сложно встретить эти ограничения.

Обратите внимание, что, хотя можно использовать полномасштабную многозадачность, для которой требуется использование блокировок по всему месту в любое время, когда общее состояние изменяется. Поскольку коммутатор coroutine никогда не будет переключаться на все, кроме вызовов yield(), любая подпрограмма может свободно изменять общее состояние, если оно обеспечивает, чтобы все в порядке до следующего выхода, и готово для другой процедуры изменять состояние "во время" выхода().

Ответ 7

Как более конкретный пример в линии производителя/потребителя, что-то столь же простое, как скромная программа пакетной отчетности, может фактически использовать совлокальные подпрограммы.

Ключевым намеком для этого примера является необходимость использования нетривиальной работы для ввода входных данных (например, анализа данных или сбора платежей и платежей в учетной записи) и нетривиальной работы для получения результата. Когда у вас есть эти характеристики:

  • Легко организовать/понять код входной стороны, если вы можете "испускать" единицы работы в разных местах.
  • Также легко организовать/понять код выходной стороны, если он может "захватить" следующую единицу работы во вложенной структуре управления.

то сопрограммы и очереди - это прекрасные методы, которые вам доступны.