Сопрограммы

Из википедии - coroutine - программный модуль, особым образом организованный для обеспечения взаимодействия с другими модулями по принципу кооперативной многозадачности: модуль приостанавливается в определённой точке, сохраняя полное состояние (включая стек вызовов и счётчик команд), и передаёт управление другому, тот, в свою очередь, выполняет задачу и передаёт управление обратно, сохраняя свои стек и счётчик. Наряду с фиберами (англ. fiber), сопрограммы являются средством обеспечения «легковесной» программной многопоточности в том смысле, что могут быть реализованы без использования механизмов переключений контекста операционной системой. Сопрограммы являются более гибкими и обобщёнными, чем подпрограммы: в сравнении с подпрограммой, имеющей всегда одну входную точку, сопрограмма имеет стартовую точку входа, за которой внутри размещены последовательность возвратов; каждый возврат также наделяется своей точкой входа. Подпрограмма может возвращаться только однажды, сопрограмма может возвращать управление несколько раз. Время работы подпрограммы определяется принципом LIFO (последняя вызванная подпрограмма завершается первой), тогда как время работы сопрограммы определяется необходимостью её запуска.
Слов много и все кажутся нужными, но запутанно, особенно с аспектом переключения контекста. Похоже, что фишка в том, что когда это делает операционная система, то это получается дороже … хотя явно это не акцентируется.
К счастью, в PicoLisp описанию этой (и реализованной) концепции посвящено достаточно текста с примерами, чтобы понять его специфику. При этом, как автором в документации, отдельной вики-статьей и в (в студенческом?) обзоре.
В своей вики автор сравнивает и демонстрирует преимущество использование сопрограмм по сравнения с функцией job (генератор?), замечая, что “Сопрограмма сохраняет локальное окружение, а также состояние управления функцией. Она может иметь несколько точек выхода и продолжать выполнение с того места, где она остановилась в прошлый раз. Это делается с помощью двух новых функций: co и yield … С точки зрения использования памяти сопрограммы довольно дороги, поскольку каждая из них требует своего собственного сегмента стека. По умолчанию основной сегмент будет ограничен 64 КБ, а каждая сопрограмма — 64 КБ. Эти значения могут увеличиваться с помощью stack. Однако, сопрограммы довольно эффективны с точки зрения накладных расходов во время выполнения … Типичным примером ситуации, когда сопрограмма может значительно упростить вещи, является рекурсивный алгоритм.“ … и, естественно, следует пример … с двоичным деревом …
В документации вместо “локального окружения“ используется “независимые контексты выполнения“ и детализируется структура - несколько точек входа и выхода … стек, привязки символов, пространства имен, кадры catch/throw и I/O между вызовами … Сопрограмма идентифицируется тегом. Этот тег может быть передан другим функциям и (повторно)вызван по мере необходимости. В этом отношении сопрограммы похожи на «продолжения» в других языках. Теги могут быть любого типа (для сравнения используется равенство указателей), но символические теги более эффективны для большого количества сопрограмм. Они кэшируют указатель на внутреннюю структуру данных в свойстве с ключом ноль (который недоступен для функций put и get). Сопрограмма останавливается и удаляется, когда
исполнение падает с конца
некоторые другие (со)программные вызовы
co
с этим тегом, но безprg
телав
throw
другую (со)программную среду выполняетсяпроизошла ошибка, и была введена обработка ошибок
Повторные co
вызовы не допускаются: сопрограмма не может вызывать или останавливать себя напрямую или косвенно.
В прочем, не менее интересно и заглянуть в обзор с оригинальными комментариями … “Сопрограммы — это тип программной конструкции, которая направлена на достижение параллелизма в программировании без использования потоков или процессов … Одним из преимуществ сопрограмм является то, что их можно использовать для написания асинхронного кода более последовательным и читаемым образом по сравнению с другими моделями параллелизма, такими как потоки или обратные вызовы. Сопрограммы можно использовать для написания кода, который выглядит как синхронный код, при этом все еще используя преимущества асинхронного поведения и избегая некоторых ловушек параллельного программирования, таких как состояния гонки и взаимоблокировки.” … В обзоре дополнительные примеры, что может помочь понять конкретное применение концепции в PicoLisp.
P.S. Где-то, из авторских текстах, отложилось, что “Потоки не нужны!” … не могу вспомнить контекст и не вижу, чтобы был, специально так обозначенный, текст … но вот ассоциации остались.
Subscribe to my newsletter
Read articles from Sergey Shishkin directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Sergey Shishkin
Sergey Shishkin
Всегда чему-то учусь!