stringtranslate.com

Корутина

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

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

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

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

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

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

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

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

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

Сравнение с

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

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

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

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

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

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

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

Темы

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

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

Генераторы

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

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

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

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

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

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

Распространенное использование

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

Собственная поддержка

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

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

Реализации

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

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

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

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

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

С

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

После получения второго стека вызовов одним из перечисленных выше методов функции setjmp и longjmp в стандартной библиотеке C могут быть использованы для реализации переключений между сопрограммами. Эти функции сохраняют и восстанавливают, соответственно, указатель стека , счетчик программ , сохраненные вызываемым объектом регистры и любое другое внутреннее состояние, требуемое ABI , так что возврат к сопрограмме после выполнения yield восстанавливает все состояние, которое было бы восстановлено при возврате из вызова функции. Минималистские реализации, которые не используют функции 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] ribs2, [35] libdill., [36] libaco, [37] и libco. [26]

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

С++

С#

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

Кложур

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

Д

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

Идти

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

Ява

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

JavaScript

Начиная с ECMAScript 2015 , JavaScript поддерживает генераторы , которые являются особым случаем сопрограмм. [53]

Котлин

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

Луа

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

Модула-2

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

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

Мононуклеоз

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

.NET Framework

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

OCaml

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

Перл

Сопрограммы изначально реализованы во всех бэкэндах Raku . [61]

PHP

Питон

Ракетка

Racket предоставляет собственные продолжения с тривиальной реализацией сопрограмм, представленной в официальном каталоге пакетов. Реализация от S. De Gabrielle

Рубин

Схема

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

Smalltalk

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

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

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

Вала

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

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

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

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

Ссылки

  1. ^ "Какого черта async/await работает в Python 3.5?". Высокий, язвительный канадец . 2016-02-11 . Получено 2023-01-10 .
  2. ^ Кнут, Дональд Эрвин (1997). Фундаментальные алгоритмы (PDF) . Искусство программирования. Том 1 (3-е изд.). Эддисон-Уэсли. Раздел 1.4.5: История и библиография, стр. 229. ISBN 978-0-201-89683-1. Архивировано (PDF) из оригинала 2019-10-21.
  3. ^ Конвей, Мелвин Э. (июль 1963 г.). «Проект компилятора разделяемых переходных диаграмм» (PDF) . Сообщения ACM . 6 (7). ACM: 396–408. doi :10.1145/366663.366704. ISSN  0001-0782. S2CID  10559786 – через цифровую библиотеку ACM.
  4. ^ Марлин, Кристофер (1980). Сопрограммы: методология программирования, разработка языка и реализация . Springer. ISBN 3-540-10256-6.
  5. ^ Ана Люсия де Моура; Роберто Иерусалимши (2009). «Возвращаясь к сопрограммам». Труды ACM по языкам и системам программирования . 31 (2): 1–31. CiteSeerX 10.1.1.58.4017 . doi :10.1145/1462166.1462167. S2CID  9918449. 
  6. ^ ab Knuth, Donald Ervin (1997). Фундаментальные алгоритмы . Искусство программирования. Том 1 (3-е изд.). Addison-Wesley. Раздел 1.4.2: Сопрограммы, стр. 193–200. ISBN 978-0-201-89683-1.
  7. ^ Perlis, Alan J. (сентябрь 1982 г.). «Эпиграммы о программировании». ACM SIGPLAN Notices . 17 (9): 7–13. doi : 10.1145/947955.1083808 . S2CID  20512767. Архивировано из оригинала 17 января 1999 г. 6. Симметрия — это концепция снижения сложности (сопрограммы включают подпрограммы); ищите ее везде
  8. ^ Энтони Ралстон (2000). Энциклопедия компьютерных наук. Nature Pub. Group. ISBN 978-1-56159-248-7. Получено 11 мая 2013 г.
  9. ^ См., например, Справочник по языку Python "https://docs.python.org/reference/expressions.html#yieldexpr 5.2.10. Выражения Yield]":
    "Все это делает функции генератора весьма похожими на сопрограммы; они возвращают управление несколько раз, имеют более одной точки входа, и их выполнение может быть приостановлено. Единственное отличие состоит в том, что функция генератора не может контролировать, где должно продолжаться выполнение после того, как она возвращает управление; управление всегда передается вызывающей стороне генератора".
  10. ^ Мерц, Дэвид (1 июля 2002 г.). "Генераторные машины состояний". Charming Python . IBM developerWorks. Архивировано из оригинала 28 февраля 2009 г. Получено 2 февраля 2011 г.
  11. ^ «Корутины: безопасные по типу сопрограммы, использующие облегченные типы сеансов».
  12. ^ «Сопрограммы в Haskell».
  13. ^ "Модуль сопрограмм (coroutines.hhf)". Руководство по стандартной библиотеке HLA .
  14. ^ "Новое в JavaScript 1.7". Архивировано из оригинала 2009-03-08 . Получено 2018-06-18 .
  15. ^ «Руководство Julia — Поток управления — Задачи (также известные как сопрограммы)».
  16. ^ «Что нового в Kotlin 1.1».
  17. ^ "Справочное руководство Lua 5.2". www.lua.org .
  18. ^ "Python async/await Tutorial". Stack Abuse . 17 декабря 2015 г.
  19. ^ "8. Составные операторы — Документация Python 3.8.0". docs.python.org .
  20. ^ «Сбор и/или сопрограммы». 2012-12-19.
  21. ^ Dahl, OJ; Hoare, CAR, ред. (1972). "Иерархические структуры программ". Структурное программирование . Лондон, Великобритания: Academic Press. стр. 175–220. ISBN 978-0-12-200550-3.
  22. ^ Маккартни, Дж. «Переосмысление языка программирования компьютерной музыки: SuperCollider». Computer Music Journal, 26(4):61-68. MIT Press, 2002.
  23. ^ Реализация сопрограмм для .NET путем обертывания неуправляемого API Fiber Архивировано 07.09.2008 на Wayback Machine , Аджай Шанкар, журнал MSDN
  24. ^ abc "Сопрограммы на языке C – brainwagon". 5 марта 2005 г.
  25. ^ Ральф С. Энгельшалл (18–23 июня 2000 г.). Переносимая многопоточность – трюк со стеком сигналов для создания потоков в пользовательском пространстве (PS) . Ежегодная техническая конференция USENIX. Сан-Диего, США.
  26. ^ ab "libco". 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: переносимая реализация сопрограммы". Архивировано из оригинала 2019-11-12 . Получено 2013-09-06 .для FreeBSD, Linux, OS X PPC и x86, SunOS, Symbian и других
  33. ^ "libconcurrency — масштабируемая библиотека параллелизма для C".простая библиотека C для переносимых сопрограмм переключения стека
  34. ^ "libcoro: C-библиотека, реализующая сопрограммы (кооперативную многозадачность) в переносимой форме".используется в качестве основы для модуля Coro perl.
  35. ^ "RIBS (Robust Infrastructure for Backend Systems) версия 2: aolarchive/ribs2". 13 августа 2019 г. – через GitHub.
  36. ^ "libdill". libdill.org . Архивировано из оригинала 2019-12-02 . Получено 2019-10-21 .
  37. ^ "Невероятно быстрая и легкая библиотека асимметричных корутин C 💎 ⛅🚀⛅🌞: hnes/libaco". 21 октября 2019 г. – через GitHub.
  38. ^ ab Саймон Тэтхэм (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 г.). «Итераторы». Документация C# . Microsoft – через Microsoft Learn.
  45. ^ Вагнер, Билл (13 февраля 2023 г.). «История C#». Документация C# . Microsoft . C# версии 2.0 – через Microsoft Learn.
  46. ^ "Goroutines - Effective Go". go.dev . Получено 28.11.2022 .
  47. ^ "Операторы Go - Спецификация Go". go.dev . Получено 28.11.2022 .
  48. ^ "Goroutines - A Tour of Go". go.dev . Получено 28.11.2022 .
  49. ^ «Часто задаваемые вопросы (FAQ) — Язык программирования Go». go.dev .
  50. ^ "Корутины для Go". swtch.com . Получено 2024-10-24 .
  51. ^ Лукас Штадлер (2009). "JVM Continuations" (PDF) . JVM Language Summit.
  52. ^ Remi Forax (19 ноября 2009 г.). "Боже мой: JVM имеет сопрограмму/продолжение/волокно и т. д.". Архивировано из оригинала 19 марта 2015 г.
  53. ^ "ECMAScript 6: Новые возможности: Обзор и сравнение - Протокол итератора функции генератора". es6-features.org . Архивировано из оригинала 18 марта 2018 г. . Получено 19 марта 2018 г. .{{cite web}}: CS1 maint: неподходящий URL ( ссылка )
  54. ^ "История версий Lua". Lua.org .
  55. ^ де Моура, Ана Люсия; Родригес, Ноэми; Иерусалимский, Роберто. «Сопрограммы в Lua» (PDF) . Луа.орг . Проверено 24 апреля 2023 г.
  56. ^ де Моура, Ана Люсия; Родригес, Ноэми; Иерусалимский, Роберто (2004). «Сопрограммы в Lua». Журнал универсальной информатики . 10 (7): 901-924.
  57. ^ http://www.mono-project.com/Продолжения Моно Продолжения
  58. ^ http://blogs.msdn.com/cbrumme/archive/2004/02/21/77595.aspx, Крис Брамме, веб-журнал cbrumme
  59. ^ kexugit (15 сентября 2005 г.). "Fiber mode is gone..." docs.microsoft.com . Получено 2021-06-08 .
  60. ^ "Библиотека потоков".
  61. ^ "RFC №31".
  62. ^ "Что нового в Python 3.7" . Получено 10 сентября 2021 г. .
  63. ^ "полукорутины". Архивировано из оригинала 24 октября 2007 г.
  64. ^ "страница руководства по сопрограммам - Встроенные команды Tcl". Tcl.tk . Получено 27.06.2016 .
  65. ^ Ритчи, Деннис М. (1980). «Эволюция системы разделения времени Unix». Проектирование языка и методология программирования. Конспект лекций по информатике. Том 79. С. 25–35. doi :10.1007/3-540-09745-7_2. ISBN 978-3-540-09745-7. S2CID  571269. Архивировано из оригинала 2015-04-08 . Получено 2011-01-26 .

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

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