stringtranslate.com

Сопрограмма

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

Их описывают как «функции, выполнение которых можно приостановить». [1]

Мелвин Конвей ввёл термин «сопрограмма» в 1958 году, когда применил его к построению ассемблерной программы . [2] Первое опубликованное объяснение сопрограммы появилось позже, в 1963 году. [3]

Определение и типы

Не существует единого точного определения сопрограммы. В 1980 году Кристофер Д. Марлин [4] суммировал две широко признанные фундаментальные характеристики сопрограммы:

  1. значения данных, локальных для сопрограммы, сохраняются между последовательными вызовами;
  2. выполнение сопрограммы приостанавливается, когда управление покидает ее, только для продолжения с того места, где оно было остановлено, когда управление снова входит в сопрограмму на более позднем этапе.

Кроме того, реализация сопрограммы имеет 3 особенности:

  1. механизм передачи управления. Асимметричные сопрограммы обычно предоставляют такие ключевые слова, как yieldи resume. Программисты не могут свободно выбирать, какому кадру уступить. Среда выполнения уступает только ближайшему вызывающему объекту текущей сопрограммы. С другой стороны, в симметричной сопрограмме программисты должны указать пункт назначения вывода.
  2. предусмотрены ли в языке сопрограммы как первоклассные объекты , которыми программист может свободно манипулировать, или как ограниченные конструкции;
  3. может ли сопрограмма приостановить свое выполнение из вызовов вложенных функций. Такая сопрограмма является стековой . Другой вариант называется сопрограммой без стека , где, если она не отмечена как сопрограмма, обычная функция не может использовать ключевое слово yield.

В журнале Revisiting Coroutines [5] , опубликованном в 2009 году, был предложен термин « Полная сопрограмма» для обозначения программы, которая поддерживает первоклассную сопрограмму и является стековой. Полные сопрограммы заслуживают собственного названия, поскольку они обладают той же выразительной силой , что и одноразовые продолжения и продолжения с разделителями. Полные сопрограммы бывают симметричными или асимметричными. Важно отметить, что то, является ли сопрограмма симметричной или асимметричной, не влияет на то, насколько выразительной она может быть, поскольку они одинаково выразительны, хотя полные сопрограммы более выразительны, чем неполные сопрограммы. Хотя их выразительная сила одинакова, асимметричные сопрограммы больше напоминают структуры управления, основанные на подпрограммах, в том смысле, что управление всегда передается обратно вызывающей стороне, что программистам может показаться более знакомым.

В сравнении с

Подпрограммы

Подпрограммы — это частные случаи сопрограмм. [6] При вызове подпрограммы выполнение начинается с самого начала, и как только подпрограмма завершается, она завершается; экземпляр подпрограммы возвращает значение только один раз и не сохраняет состояние между вызовами. Напротив, сопрограммы могут завершиться, вызвав другие сопрограммы, которые позже могут вернуться к тому месту, где они были вызваны в исходной сопрограмме; с точки зрения сопрограммы, это не выход, а вызов другой сопрограммы. [6] Таким образом, экземпляр сопрограммы сохраняет состояние и меняется между вызовами; одновременно может существовать несколько экземпляров данной сопрограммы. Разница между вызовом другой сопрограммы посредством «уступки» ей и простым вызовом другой подпрограммы (которая затем также вернется в исходную точку) заключается в том, что отношения между двумя сопрограммами, которые уступают друг другу, не являются отношениями вызывающего -вызываемый, но вместо этого симметричный.

Любую подпрограмму можно преобразовать в сопрограмму, которая не вызывает выход . [7]

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

var q := новая очередьсопрограмма создает цикл  , пока q не заполнен создать несколько новых предметов добавить элементы в q урожай , чтобы потреблятьцикл потребления сопрограммы , пока q не пуст удалить некоторые элементы из q использовать предметы урожайность , чтобы произвестипозвонить, произвести

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

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

Потоки

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

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

Генераторы

Генераторы, также известные как полукорутины, [8] представляют собой подмножество сопрограмм. В частности, хотя обе могут выполнять несколько раз, приостанавливая свое выполнение и разрешая повторный вход в нескольких точках входа, они различаются способностью сопрограмм контролировать, где выполнение продолжается сразу после завершения, в то время как генераторы не могут, вместо этого передавая управление обратно вызывающей стороне генератора. . [9] То есть, поскольку генераторы в основном используются для упрощения написания итераторов , yieldоператор в генераторе не определяет сопрограмму для перехода, а скорее передает значение обратно родительской подпрограмме.

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

var q := новая очередьгенератор создает цикл  , пока q не заполнен создать несколько новых предметов добавить элементы в q урожайцикл потребления генератора , пока q не пуст удалить некоторые элементы из q использовать предметы урожайдиспетчер подпрограмм var d := новый словарь( генераторитератор ) d[производить] := начать производить d[consume] := начало потребления var current := создание тока вызова цикла  текущий := следующий d[текущий]позвонить диспетчеру

Ряд реализаций сопрограмм для языков с поддержкой генераторов, но без собственных сопрограмм (например, Python [10] до версии 2.5) используют эту или аналогичную модель.

Взаимная рекурсия

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

Обычное использование

Сопрограммы полезны для реализации следующего:

Встроенная поддержка

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

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

Реализации

По состоянию на 2003 год многие из наиболее популярных языков программирования, включая C и его производные, не имеют встроенной поддержки сопрограмм внутри языка или его стандартных библиотек. Во многом это связано с ограничениями реализации подпрограмм на основе стека . Исключением является библиотека C++ Boost.Context, входящая в состав библиотек boost, которая поддерживает замену контекста в ARM, MIPS, PowerPC, SPARC и x86 в POSIX, Mac OS X и Windows. Сопрограммы могут быть построены на Boost.Context.

В ситуациях, когда сопрограмма была бы естественной реализацией механизма, но недоступна, типичным ответом является использование замыкания –  подпрограммы с переменными состояния ( статическими переменными , часто логическими флагами) для поддержания внутреннего состояния между вызовами и передать управление в нужную точку. Условные выражения внутри кода приводят к выполнению различных путей кода при последовательных вызовах в зависимости от значений переменных состояния. Другой типичный ответ — реализация явного конечного автомата в форме большого и сложного оператора переключения или с помощью оператора перехода , в частности вычисляемого перехода . Такие реализации считаются трудными для понимания и поддержки и являются мотивацией для поддержки сопрограмм.

Потоки и, в меньшей степени , волокна являются сегодня альтернативой сопрограммам в основных средах программирования. Потоки предоставляют средства для управления совместным взаимодействием одновременно выполняющихся фрагментов кода в реальном времени. Потоки широко доступны в средах, поддерживающих C (и поддерживаются изначально во многих других современных языках), знакомы многим программистам и обычно хорошо реализованы, хорошо документированы и хорошо поддерживаются. Однако, поскольку они решают большую и сложную проблему, они включают в себя множество мощных и сложных средств и, соответственно, требуют сложного обучения. Таким образом, когда все, что необходимо, — это сопрограмма, использование потока может оказаться излишним.

Одним из важных различий между потоками и сопрограммами является то, что потоки обычно планируются заранее, а сопрограммы — нет. Поскольку потоки могут быть перепланированы в любой момент и могут выполняться одновременно, программы, использующие потоки, должны быть осторожны с блокировкой . Напротив, поскольку сопрограммы можно перепланировать только в определенных точках программы и они не выполняются одновременно, программы, использующие сопрограммы, часто могут полностью избежать блокировки. Это свойство также считается преимуществом событийно-управляемого или асинхронного программирования.

Поскольку волокна планируются совместно, они обеспечивают идеальную основу для реализации описанных выше сопрограмм. [23] Однако системная поддержка волокон часто отсутствует по сравнению с поддержкой потоков.

С

Для реализации сопрограмм общего назначения необходимо получить второй стек вызовов , что не поддерживается языком C напрямую . Надежный (хотя и специфичный для платформы) способ добиться этого — использовать небольшой объем встроенной сборки для явного управления указателем стека во время первоначального создания сопрограммы. Это подход, рекомендованный Томом Даффом в обсуждении его относительных преимуществ по сравнению с методом, используемым Protothreads . [24] [ необходим неосновной источник ] На платформах, которые предоставляют системный вызов sigaltstack POSIX , второй стек вызовов можно получить, вызвав функцию трамплина из обработчика сигнала [25] [26] для достижения той же цели в переносимых C, ценой некоторой дополнительной сложности. Библиотеки C, соответствующие POSIX или Единой спецификации Unix (SUSv3), предоставляют такие процедуры, как getcontext, setcontext, makecontext и swapcontext , но эти функции были объявлены устаревшими в POSIX 1.2008. [27]

Как только второй стек вызовов будет получен с помощью одного из перечисленных выше методов, функции setjmp и longjmp в стандартной библиотеке C можно использовать для реализации переключения между сопрограммами. Эти функции сохраняют и восстанавливают, соответственно, указатель стека , программный счетчик , регистры , сохраненные вызываемым абонентом , и любое другое внутреннее состояние, как того требует ABI , так что возврат к сопрограмме после возврата восстанавливает все состояние, которое будет восстановлено при возврате. из вызова функции. Минималистские реализации, которые не используют функции setjmp и longjmp, могут достичь того же результата с помощью небольшого блока встроенного ассемблера , который меняет местами только указатель стека и программный счетчик и затирает все остальные регистры. Это может быть значительно быстрее, поскольку setjmp и longjmp должны консервативно хранить все регистры, которые могут использоваться в соответствии с ABI, тогда как метод clobber позволяет компилятору хранить (путем передачи в стек) только то, что, как он знает, действительно используется.

Из-за отсутствия прямой языковой поддержки многие авторы написали свои собственные библиотеки для сопрограмм, которые скрывают вышеуказанные детали. Библиотека libtask Расса Кокса [28] является хорошим примером этого жанра. Он использует функции контекста, если они предоставляются встроенной библиотекой C; в противном случае он предоставляет свои собственные реализации для ARM, PowerPC, Sparc и x86. Другие известные реализации включают libpcl, [29] coro, [30] lthread, [31] libCoroutine, [32] libconcurrency, [33] libcoro, [34] ребра2, [35] libdill., [36] libaco, [37] и Либко. [26]

В дополнение к общему подходу, описанному выше, было предпринято несколько попыток аппроксимировать сопрограммы в C комбинациями подпрограмм и макросов. Вклад Саймона Тэтэма [38] , основанный на устройстве Даффа , является ярким примером этого жанра и лежит в основе Protothreads и подобных реализаций. [39] В дополнение к возражениям Даффа, [24] собственные комментарии Тэтэма дают откровенную оценку ограничений этого подхода: «Насколько мне известно, это худший образец хакерства на языке C, когда-либо виденный в серьезном производственном коде». [38] Основные недостатки этого приближения заключаются в том, что из-за отсутствия отдельного кадра стека для каждой сопрограммы локальные переменные не сохраняются при выходе из функции, невозможно иметь несколько записей в функции, а управление может только быть получено из подпрограммы верхнего уровня. [24]

С++

С#

В C# 2.0 добавлена ​​функциональность полусопрограммы ( генератора ) посредством шаблона и yieldключевого слова итератора. [44] [45] C# 5.0 включает поддержку синтаксиса ожидания . Кроме того:

Клоджур

Cloroutine — сторонняя библиотека, обеспечивающая поддержку бесстековых сопрограмм в Clojure . Он реализован как макрос, статически разбивающий произвольный блок кода на произвольные вызовы var и выдающий сопрограмму как функцию с состоянием.

Д

D реализует сопрограммы в качестве класса стандартной библиотеки. Генератор Fiber A упрощает представление функции волокна в качестве входного диапазона , делая любое волокно совместимым с существующими алгоритмами диапазона.

Идти

В Go есть встроенная концепция « горутин », которые представляют собой легкие, независимые процессы, управляемые средой выполнения Go. Новую горутину можно запустить с помощью ключевого слова «go». Каждая горутина имеет стек переменного размера, который можно расширять по мере необходимости. Горутины обычно взаимодействуют, используя встроенные каналы Go. [46] [47] [48] [49]

Джава

В Java существует несколько реализаций сопрограмм . Несмотря на ограничения, налагаемые абстракциями Java, JVM не исключает такой возможности. [50] Используются четыре общих метода, но два из них нарушают переносимость байт-кода среди JVM, соответствующих стандартам.

JavaScript

Котлин

Kotlin реализует сопрограммы как часть собственной библиотеки.

Луа

Lua поддерживает первоклассные стековые асимметричные сопрограммы, начиная с версии 5.0 (2003 г.), [52] в стандартной библиотеке coroutine . [53] [54]

Модуль-2

Modula-2 , как определено Виртом , реализует сопрограммы как часть стандартной библиотеки SYSTEM.

Процедура NEWPROCESS() заполняет контекст, заданный блоком кода и пространством для стека в качестве параметров, а процедура TRANSFER() передает управление сопрограмме, учитывая контекст сопрограммы в качестве параметра.

Мононуклеоз

Среда выполнения Mono Common Language поддерживает продолжения, [55] из которых могут быть построены сопрограммы.

.NET Framework

Во время разработки .NET Framework 2.0 компания Microsoft расширила дизайн API-интерфейсов хостинга Common Language Runtime (CLR) для управления планированием на основе оптоволокна с прицелом на его использование в режиме оптоволокна для SQL-сервера. [56] Перед выпуском поддержка перехватчика переключения задач ICLRTask::SwitchOut была удалена из-за нехватки времени. [57] Следовательно, использование Fiber API для переключения задач в настоящее время не является жизнеспособным вариантом в .NET Framework. [ нужно обновить ]

OCaml

OCaml поддерживает сопрограммы через свой Threadмодуль. [58] Эти сопрограммы обеспечивают параллелизм без параллелизма и заранее планируются для одного потока операционной системы. Начиная с OCaml 5.0, также доступны зеленые потоки ; обеспечивается различными модулями.

Перл

Сопрограммы встроены во все серверные части Raku . [59]

PHP

Питон

Ракетка

Racket предоставляет собственные продолжения с тривиальной реализацией сопрограмм, представленных в официальном каталоге пакетов. Реализация С. Де Габриэль

Рубин

Схема

Поскольку Scheme обеспечивает полную поддержку продолжений, реализация сопрограмм почти тривиальна и требует только поддержания очереди продолжений.

Болтовня

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

Язык команд инструмента (Tcl)

Начиная с версии 8.6, язык команд инструментов поддерживает сопрограммы на основном языке.[62]

Вала

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

Языки ассемблера

Машинно-зависимые языки ассемблера часто предоставляют прямые методы для выполнения сопрограмм. Например, в MACRO-11 , ассемблере семейства миникомпьютеров PDP-11 , «классическое» переключение сопрограммы осуществляется с помощью инструкции «JSR PC,@(SP)+», которая переходит по адресу, полученному из стек и помещает в стек адрес текущей ( т. е. следующей ) инструкции. В VAXenVAX MACRO ) сопоставимой инструкцией является «JSB @(SP)+». Даже на Motorola 6809 есть инструкция "JSR[,S++]"; обратите внимание на «++», поскольку 2 байта (адреса) извлекаются из стека. Эта инструкция часто используется в (стандартном) «мониторном» Assist 09.

Смотрите также

Рекомендации

  1. ^ «Как, черт возьми, работает async/await в Python 3.5?». Высокий, язвительный канадец . 11 февраля 2016 г. Проверено 10 января 2023 г.
  2. ^ Кнут, Дональд Эрвин (1997). Фундаментальные алгоритмы (PDF) . Искусство компьютерного программирования. Том. 1 (3-е изд.). Аддисон-Уэсли. Раздел 1.4.5: История и библиография, стр. 229. ISBN. 978-0-201-89683-1. Архивировано (PDF) из оригинала 21 октября 2019 г.
  3. ^ Конвей, Мелвин Э. (июль 1963 г.). «Проектирование компилятора разделимых диаграмм переходов» (PDF) . Коммуникации АКМ . АКМ. 6 (7): 396–408. дои : 10.1145/366663.366704. ISSN  0001-0782. S2CID  10559786 - через цифровую библиотеку ACM.
  4. ^ Марлин, Кристофер (1980). Сопрограммы: методология программирования, языковой дизайн и реализация . Спрингер. ISBN 3-540-10256-6.
  5. ^ Ана Люсия де Моура; Роберто Иерусалимский (2009). «Возвращение к сопрограммам». Транзакции ACM в языках и системах программирования . 31 (2): 1–31. CiteSeerX 10.1.1.58.4017 . дои : 10.1145/1462166.1462167. S2CID  9918449. 
  6. ^ аб Кнут, Дональд Эрвин (1997). Фундаментальные алгоритмы . Искусство компьютерного программирования. Том. 1 (3-е изд.). Аддисон-Уэсли. Раздел 1.4.2: Сопрограммы, стр. 193–200. ISBN 978-0-201-89683-1.
  7. ^ Перлис, Алан Дж. (сентябрь 1982 г.). «Эпиграммы по программированию». Уведомления ACM SIGPLAN . 17 (9): 7–13. дои : 10.1145/947955.1083808 . S2CID  20512767. Архивировано 17 января 1999 года. 6. Симметрия — это концепция снижения сложности (сопрограммы включают подпрограммы); ищи это везде
  8. ^ Энтони Ралстон (2000). Энциклопедия информатики. Природный паб. Группа. ISBN 978-1-56159-248-7. Проверено 11 мая 2013 г.
  9. ^ См., например , Справочник по языку Python «https://docs.python.org/reference/expressions.html#yieldexpr 5.2.10. Выражения доходности]»:
    «Все это делает функции генератора очень похожими на сопрограммы; они возвращают несколько раз они имеют более одной точки входа, и их выполнение может быть приостановлено. Единственное отличие состоит в том, что функция-генератор не может контролировать, где должно продолжаться выполнение после ее завершения; управление всегда передается вызывающей стороне генератора».
  10. Мерц, Дэвид (1 июля 2002 г.). «Конечные автоматы на основе генераторов». Очаровательный питон . IBM DeveloperWorks. Архивировано из оригинала 28 февраля 2009 года . Проверено 2 февраля 2011 г.
  11. ^ «Сопрограмма: типобезопасные сопрограммы, использующие облегченные типы сеансов» .
  12. ^ «Сопрограммы в Haskell».
  13. ^ "Модуль сопрограмм (coroutines.hhf)" . Руководство по стандартной библиотеке HLA .
  14. ^ «Новое в JavaScript 1.7» . Архивировано из оригинала 8 марта 2009 г. Проверено 18 июня 2018 г.
  15. ^ «Руководство Джулии — Поток управления — Задачи (также известные как сопрограммы)» .
  16. ^ «Что нового в Kotlin 1.1» .
  17. ^ «Справочное руководство по Lua 5.2» . www.lua.org .
  18. ^ «Учебное пособие по Python async/await» . Злоупотребление стеком . 17 декабря 2015 г.
  19. ^ «8. Составные операторы — документация Python 3.8.0» . docs.python.org .
  20. ^ «Сбор и/или сопрограммы». 19 декабря 2012 г.
  21. ^ Даль, О.Дж.; Хоар, CAR, ред. (1972). «Иерархические структуры программы». Структурное программирование . Лондон, Великобритания: Академическая пресса. стр. 175–220. ISBN 978-0-12-200550-3.
  22. ^ Маккартни, Дж. «Переосмысление языка компьютерного музыкального программирования: SuperCollider». Компьютерный музыкальный журнал, 26 (4): 61-68. МИТ Пресс, 2002.
  23. ^ Реализация сопрограмм для .NET путем упаковки неуправляемого Fiber API. Архивировано 7 сентября 2008 г. в Wayback Machine , Аджай Шанкар, журнал MSDN.
  24. ^ abc "Сопрограммы в C - мозговой вагон" .
  25. ^ Ральф С. Энгельшалл (18–23 июня 2000 г.). Портативная многопоточность: трюк со стеком сигналов для создания потоков в пользовательском пространстве (PS) . Ежегодная техническая конференция USENIX. Сан-Диего, США.
  26. ^ аб "либко". code.byuu.org .[ постоянная мертвая ссылка ]
  27. ^ «getcontext(3) — страница руководства Linux» . man7.org .
  28. ^ http://swtch.com/libtask/ — библиотека сопрограмм libtask Расса Кокса для FreeBSD, Linux, Mac OS X и SunOS.
  29. ^ Портативная библиотека сопрограмм — библиотека C, использующая возможности POSIX/SUSv3.
  30. ^ http://www.goron.de/~froese/coro/. Архивировано 10 января 2006 г. в Wayback Machine — библиотека coro Эдгара Торнига для x86, Linux и FreeBSD.
  31. ^ https://github.com/halayli/lthread — lthread — это многоядерная/многопоточная библиотека сопрограмм, написанная на C.
  32. ^ «libcoroutine: переносимая реализация сопрограммы» . Архивировано из оригинала 12 ноября 2019 г. Проверено 6 сентября 2013 г.для FreeBSD, Linux, OS X PPC и x86, SunOS, Symbian и других
  33. ^ «libconcurrency — масштабируемая библиотека параллелизма для C» .простая библиотека C для портативных сопрограмм переключения стека
  34. ^ «libcoro: C-библиотека, которая реализует сопрограммы (совместную многозадачность) портативным способом» .используется в качестве основы для Perl-модуля Coro.
  35. ^ «RIBS (Надежная инфраструктура для серверных систем) версия 2: aolarchive/ribs2» . 13 августа 2019 г. – через GitHub.
  36. Ссылки _ libdill.org . Архивировано из оригинала 2 декабря 2019 г. Проверено 21 октября 2019 г.
  37. ^ «Невероятно быстрая и легкая библиотека асимметричных сопрограмм C 💎 ⛅🚀⛅🌞: hnes/libaco» . 21 октября 2019 г. – через GitHub.
  38. ^ аб Саймон Тэтэм (2000). «Сопрограммы в C».
  39. ^ «Реализация бесстековой сопрограммы в C и C++: jsseldenthuis/coroutine» . 18 марта 2019 г. – через GitHub.
  40. ^ http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4680.pdf - Техническая спецификация сопрограмм.
  41. ^ https://en.cppreference.com/w/cpp/compiler_support#cpp20 — Текущая поддержка компилятором стандартных сопрограмм.
  42. ^ http://mozy.com/blog/announcements/open-source-and-mozy-the-debut-of-mozy-code/ - Открытый исходный код и Mozy: дебют кода Mozy
  43. ^ https://twitter.com/eric01/status/867473461836263424 - EricWF: Сопрограммы теперь в Clang Trunk! Сейчас работаю над реализацией Libc++.
  44. Вагнер, Билл (11 ноября 2021 г.). «Итераторы». Документация С# . Microsoft – через Microsoft Learn.
  45. Вагнер, Билл (13 февраля 2023 г.). «История C#». Документация С# . Майкрософт . C# версии 2.0 — через Microsoft Learn.
  46. ^ "Горутины - Эффективное движение" . go.dev . Проверено 28 ноября 2022 г.
  47. ^ «Операторы Go - Спецификация Go» . go.dev . Проверено 28 ноября 2022 г.
  48. ^ "Горутины - экскурсия по го" . go.dev . Проверено 28 ноября 2022 г.
  49. ^ «Часто задаваемые вопросы (FAQ) - Язык программирования Go» . go.dev .
  50. ^ Лукас Стадлер (2009). «Продолжение JVM» (PDF) . Языковой саммит JVM.
  51. Реми Форакс (19 ноября 2009 г.). «Черт возьми: у JVM есть сопрограмма/продолжение/волокно и т. д.». Архивировано из оригинала 19 марта 2015 года.
  52. ^ "История версий Lua" . Луа.орг .
  53. ^ де Моура, Ана Люсия; Родригес, Ноэми; Иерусалимский, Роберто. «Сопрограммы в Lua» (PDF) . Луа.орг . Проверено 24 апреля 2023 г.
  54. ^ де Моура, Ана Люсия; Родригес, Ноэми; Иерусалимский, Роберто (2004). «Сопрограммы в Lua». Журнал универсальной информатики . 10 (7): 901-924.
  55. ^ http://www.mono-project.com/Continuations Моно-продолжения
  56. ^ http://blogs.msdn.com/cbrumme/archive/2004/02/21/77595.aspx, Крис Брамме, веб-журнал cbrumme
  57. ^ kexugit (15 сентября 2005 г.). «Режим оптоволокна пропал…» docs.microsoft.com . Проверено 8 июня 2021 г.
  58. ^ "Библиотека потоков" .
  59. ^ "RFC № 31" .
  60. ^ «Что нового в Python 3.7» . Проверено 10 сентября 2021 г.
  61. ^ "Полусопрограммы". Архивировано из оригинала 24 октября 2007 года.
  62. ^ "Страница руководства по сопрограмме - Встроенные команды Tcl" . Tcl.tk. _ Проверено 27 июня 2016 г.
  63. ^ Ричи, Деннис М. (1980). «Эволюция системы разделения времени Unix». Языковой дизайн и методология программирования. Конспекты лекций по информатике. Том. 79. С. 25–35. дои : 10.1007/3-540-09745-7_2. ISBN 978-3-540-09745-7. S2CID  571269. Архивировано из оригинала 8 апреля 2015 г. Проверено 26 января 2011 г.

дальнейшее чтение

Внешние ссылки