Каковы варианты использования сопрограммы?

StackOverflow https://stackoverflow.com/questions/303760

  •  08-07-2019
  •  | 
  •  

Вопрос

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

Это было полезно?

Решение

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

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

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

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

Другие советы

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Без сопрограмм либо подсистему пользовательского интерфейса, либо подсистему модема пришлось бы реализовывать с использованием конечного автомата.Использование сопрограмм позволяет написать обе подсистемы в наиболее естественном стиле.Обратите внимание, что важно, чтобы ни одна подсистема никогда не работала слишком долго без перевода вещей в «согласованное» состояние и вызова метода методу return(), а также не вызывала метод yield() без предварительного перевода вещей в «согласованное» состояние, но обычно нетрудно выполнить эти требования. ограничения.

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

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

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

  • Код на стороне ввода легко организовать/понять, если вы можете «испускать» единицы работы в разных местах.
  • Аналогично легко организовать/понять код на стороне вывода, если он может «захватить» следующую единицу работы во вложенной структуре управления.

тогда сопрограммы и очереди — хорошие методы, которые можно иметь в своем распоряжении.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top