Сопрограммы - это компоненты компьютерной программы, которые обобщают подпрограммы для невытесняющей многозадачности , позволяя приостанавливать и возобновлять выполнение. Сопрограммы хорошо подходят для реализации знакомых программных компонентов, таких как совместные задачи , исключения , циклы событий , итераторы , бесконечные списки и конвейеры .
По словам Дональда Кнута , Мелвин Конвей ввел термин сопрограмма в 1958 году, когда применил его к построению программы сборки . [1] Первое опубликованное объяснение сопрограммы появилось позже, в 1963 году. [2]
Сравнение с подпрограммами
Подпрограммы - это частные случаи сопрограмм. [3] Когда вызываются подпрограммы, выполнение начинается с самого начала, а после выхода из подпрограммы оно завершается; экземпляр подпрограммы возвращается только один раз и не сохраняет состояние между вызовами. Напротив, сопрограммы могут завершиться путем вызова других сопрограмм, которые позже могут вернуться в точку, в которой они были вызваны в исходной сопрограмме; с точки зрения сопрограммы, это не выход, а вызов другой сопрограммы. [3] Таким образом, экземпляр сопрограммы сохраняет состояние и варьируется между вызовами; одновременно может быть несколько экземпляров данной сопрограммы. Разница между вызовом другой сопрограммы посредством "уступки" ей и простым вызовом другой подпрограммы (которая тогда также вернется к исходной точке) заключается в том, что отношения между двумя сопрограммами, которые уступают друг другу, не являются отношениями вызывающей стороны. -callee, но вместо этого симметричный.
Любую подпрограмму можно преобразовать в сопрограмму, которая не вызывает yield . [4]
Вот простой пример того, как могут быть полезны сопрограммы. Предположим, у вас есть отношения потребитель-производитель, в которых одна процедура создает элементы и добавляет их в очередь, а другая удаляет элементы из очереди и использует их. Из соображений эффективности вы хотите добавлять и удалять сразу несколько элементов. Код может выглядеть так:
var q: = новая очередьсопрограмма создает цикл, пока q не заполнен создать несколько новых предметов добавить элементы в q уступить потреблениюсопрограмма потребляет цикл, пока q не пусто удалить некоторые элементы из q использовать предметы урожай производитьзвонить, производить
Затем очередь полностью заполняется или опорожняется, прежде чем передать управление другой сопрограмме с помощью команды yield . Дальнейшие вызовы сопрограмм начинаются сразу после выхода во внешнем цикле сопрограмм.
Хотя этот пример часто используется как введение в многопоточность , два потока для этого не нужны: оператор yield может быть реализован путем перехода непосредственно из одной процедуры в другую.
Сравнение с потоками
Сопрограммы очень похожи на потоки . Однако сопрограммы являются многозадачными совместно , тогда как потоки обычно выполняют многозадачность с вытеснением . Это означает, что сопрограммы обеспечивают параллелизм, но не параллелизм . Преимущества сопрограмм перед потоками заключаются в том, что они могут использоваться в контексте жесткого реального времени ( переключение между сопрограммами не требует каких-либо системных вызовов или каких-либо блокирующих вызовов вообще), нет необходимости в примитивах синхронизации, таких как мьютексы , семафоры и т. Д. для защиты критических разделов , и нет необходимости в поддержке со стороны операционной системы.
Можно реализовать сопрограммы с использованием заранее запланированных потоков таким образом, чтобы это было прозрачно для вызывающего кода, но некоторые преимущества (в частности, пригодность для работы в режиме жесткого реального времени и относительная дешевизна переключения между ними) будут потеряны.
Сравнение с генераторами
Генераторы , также известные как полупрограммы [5], представляют собой подмножество сопрограмм. В частности, хотя оба могут давать результат несколько раз, приостанавливая их выполнение и разрешая повторный вход в нескольких точках входа, они различаются способностью сопрограмм контролировать, где выполнение продолжается сразу после того, как они уступают, в то время как генераторы не могут, вместо этого передавая управление обратно вызывающей стороне генератора. . [6] То есть, поскольку генераторы в основном используются для упрощения написания итераторов , yield
оператор в генераторе не указывает сопрограмму, к которой нужно перейти, а скорее передает значение обратно в родительскую процедуру.
Тем не менее, все еще возможно реализовать сопрограммы поверх средства генератора с помощью подпрограммы диспетчера верхнего уровня (по сути, трамплина ), которая явно передает управление дочерним генераторам, идентифицированным токенами, возвращаемыми от генераторов:
var q: = новая очередьгенератор создает цикл, пока q не заполнен создать несколько новых предметов добавить элементы в q урожай потреблятьгенератор потребляет цикл, пока q не пусто удалить некоторые элементы из q использовать предметы выход продукциидиспетчер подпрограмм var d: = новый словарь ( генератор → итератор ) d [производить]: = начать производство d [потребление]: = начало потребления var current: = создание тока контура : = следующий d [текущий]диспетчер звонков
Ряд реализаций сопрограмм для языков с поддержкой генератора, но без собственных сопрограмм (например, Python [7] до версии 2.5) используют эту или аналогичную модель.
Сравнение с взаимной рекурсией
Использование сопрограмм для конечных автоматов или параллелизма аналогично использованию взаимной рекурсии с хвостовыми вызовами , поскольку в обоих случаях элемент управления изменяется на другой из набора подпрограмм. Однако сопрограммы более гибкие и в целом более эффективные. Поскольку сопрограммы выдают результат, а не возвращают, а затем возобновляют выполнение, а не перезапускаются с самого начала, они могут удерживать состояние, обе переменные (как в случае закрытия) и точку выполнения, и выходы не ограничиваются нахождением в хвостовой позиции; взаимно рекурсивные подпрограммы должны либо использовать общие переменные, либо передавать состояние в качестве параметров. Кроме того, каждый взаимно рекурсивный вызов подпрограммы требует нового кадра стека (если не реализовано исключение хвостового вызова ), в то время как передача управления между сопрограммами использует существующие контексты и может быть реализована просто путем перехода.
Общее использование
Сопрограммы полезны для реализации следующего:
- Конечные автоматы внутри одной подпрограммы, где состояние определяется текущей точкой входа / выхода процедуры; это может привести к более удобочитаемому коду по сравнению с использованием goto , а также может быть реализовано через взаимную рекурсию с хвостовыми вызовами .
- Акторная модель параллелизма, например, в видеоиграх . Каждый субъект имеет свои собственные процедуры (это снова логически разделяет код), но они добровольно уступают управление центральному планировщику, который выполняет их последовательно (это форма совместной многозадачности ).
- Генераторы , и они полезны для потоков - особенно ввода / вывода - и для общего обхода структур данных.
- Связь последовательных процессов, где каждый подпроцесс является сопрограммой. Канальные входы / выходы и операции блокировки дают сопрограммы, а планировщик разблокирует их при событиях завершения. В качестве альтернативы, каждый подпроцесс может быть родительским для следующего за ним в конвейере данных (или предшествующего ему, и в этом случае шаблон может быть выражен как вложенные генераторы).
- Обратная связь, обычно используемая в математическом программном обеспечении, где такая процедура, как решатель, интегральный оценщик, ... требует использования процесса для выполнения вычислений, таких как вычисление уравнения или подынтегральное выражение.
Языки программирования с нативной поддержкой
Сопрограммы возникли как метод языка ассемблера , но поддерживаются в некоторых языках программирования высокого уровня . Ранние примеры включают Simula , [8] Smalltalk и Modula-2 . Более свежие примеры - Ruby , Lua , Julia и Go .
- Айкидо
- AngelScript
- Балерина
- BCPL
- Паскаль (Borland Turbo Pascal 7.0 с модулем uThreads)
- БЕТА
- БЛАЖЕНСТВО
- C ++ (Начиная с C ++ 20)
- C # (начиная с версии 2.0)
- ChucK
- CLU
- D
- Динамический C
- Erlang
- F #
- Фактор
- Сценарий GameMonkey
- GDScript (язык сценариев Годо)
- Идти
- Haskell [9] [10]
- Ассамблея высокого уровня [11]
- Икона
- Ио
- JavaScript (начиная с версии 1.7, стандартизирован в ECMAScript 6) [12] ECMAScript 2017 также включает поддержку ожидания .
- Юлия [13]
- Kotlin (начиная с версии 1.1) [14]
- Лимбо
- Lua [15]
- Lucid
- µC ++
- Модула-2
- Nemerle
- Perl 5 (с использованием модуля Coro )
- PHP (с HipHop , родным с PHP 5.5)
- Пиколисп
- Пролог
- Python (начиная с версии 2.5, [16] с улучшенной поддержкой с версии 3.3 и с явным синтаксисом с версии 3.5 [17] )
- Раку [18]
- Рубин
- Ржавчина (начиная с 1.39)
- Sather
- Схема
- Себя
- Симула 67
- Болтовня
- Белка
- Безстековый Python
- Суперколлайдер [19]
- Tcl (начиная с версии 8.6)
- urbiscript
Поскольку продолжения могут использоваться для реализации сопрограмм, поддерживающие их языки программирования также могут легко поддерживать сопрограммы.
Реализации
По состоянию на 2003 год[Обновить], многие из самых популярных языков программирования, включая C и его производные, не имеют прямой поддержки сопрограмм в языке или своих стандартных библиотеках. Это в значительной степени связано с ограничениями реализации подпрограмм на основе стека . Исключением является библиотека C ++ Boost.Context , часть библиотек boost , которая поддерживает подкачку контекста в ARM, MIPS, PowerPC, SPARC и x86 в POSIX, Mac OS X и Windows. Сопрограммы могут быть построены на Boost.Context.
В ситуациях, когда сопрограмма была бы естественной реализацией механизма, но недоступна, типичным ответом является использование замыкания - подпрограммы с переменными состояния ( статические переменные , часто логические флаги) для поддержания внутреннего состояния между вызовами, и передать управление в нужную точку. Условные выражения в коде приводят к выполнению различных путей кода при последовательных вызовах на основе значений переменных состояния. Другой типичный ответ - реализовать явный конечный автомат в форме большого и сложного оператора switch или с помощью оператора goto , особенно вычисляемого goto . Такие реализации считаются сложными для понимания и поддержки, а также побуждают к поддержке сопрограмм.
Сегодня потоки и, в меньшей степени, волокна являются альтернативой сопрограммам в основных средах программирования. Потоки предоставляют средства для управления совместным взаимодействием в реальном времени при одновременном выполнении фрагментов кода. Потоки широко доступны в средах, поддерживающих C (и изначально поддерживаются на многих других современных языках), знакомы многим программистам и обычно хорошо реализованы, хорошо документированы и хорошо поддерживаются. Однако, поскольку они решают большую и сложную проблему, они включают в себя множество мощных и сложных средств и, соответственно, требуют сложного обучения. Таким образом, когда все, что нужно - это сопрограмма, использование потока может быть излишним.
Одно из важных различий между потоками и сопрограммами заключается в том, что потоки обычно планируются заранее, а сопрограммы - нет. Поскольку потоки могут быть перепланированы в любой момент и могут выполняться одновременно, программы, использующие потоки, должны быть осторожны с блокировкой . Напротив, поскольку сопрограммы могут быть перепланированы только в определенных точках программы и не выполняются одновременно, программы, использующие сопрограммы, часто могут полностью избежать блокировки. Это свойство также упоминается как преимущество управляемого событиями или асинхронного программирования.
Поскольку волокна планируются совместно, они обеспечивают идеальную основу для реализации сопрограмм, описанных выше. [20] Однако системная поддержка волокон часто отсутствует по сравнению с поддержкой потоков.
Реализации для C
Для реализации сопрограмм общего назначения должен быть получен второй стек вызовов , что является функцией, не поддерживаемой напрямую языком C. Надежный (хотя и зависящий от платформы) способ добиться этого - использовать небольшое количество встроенной сборки для явного управления указателем стека во время первоначального создания сопрограммы. Это подход, рекомендованный Томом Даффом при обсуждении его относительных достоинств по сравнению с методом, используемым Protothreads . [21] На платформах, которые предоставляют системный вызов POSIX sigaltstack , второй стек вызовов может быть получен путем вызова функции трамплина из обработчика сигналов [22] [23] для достижения той же цели в переносимом C за счет некоторой дополнительная сложность. Библиотеки C, соответствующие POSIX или Single Unix Specification (SUSv3), предоставляли такие подпрограммы, как getcontext, setcontext, makecontext и swapcontext , но эти функции были объявлены устаревшими в POSIX 1.2008. [24]
После получения второго стека вызовов одним из перечисленных выше методов функции setjmp и longjmp в стандартной библиотеке C могут быть использованы для реализации переключений между сопрограммами. Эти функции сохраняют и восстанавливают, соответственно, указатель стека , счетчик программ , регистры , сохраненные вызываемым пользователем , и любое другое внутреннее состояние, требуемое ABI , так что возвращение к сопрограмме после получения восстанавливает все состояние, которое будет восстановлено при возврате. из вызова функции. Минималистские реализации, которые не совмещают функции setjmp и longjmp, могут достичь того же результата с помощью небольшого блока встроенной сборки, который меняет местами просто указатель стека и счетчик программы и затирает все остальные регистры. Это может быть значительно быстрее, так как setjmp и longjmp должны консервативно хранить все регистры, которые могут использоваться в соответствии с ABI, тогда как метод clobber позволяет компилятору сохранять (путем передачи в стек) только то, что он знает, что действительно используется.
Из-за отсутствия прямой языковой поддержки многие авторы написали свои собственные библиотеки для сопрограмм, которые скрывают вышеуказанные детали. Библиотека libtask Рассса Кокса [25] является хорошим примером этого жанра. Он использует контекстные функции, если они предоставлены собственной библиотекой C; в противном случае он предоставляет свои собственные реализации для ARM, PowerPC, Sparc и x86. Другие известные реализации включают libpcl, [26] coro, [27] lthread, [28] libCoroutine, [29] libconcurrency, [30] libcoro, [31] ribs2, [32] libdill., [33] libaco, [34] и libco. [23]
В дополнение к общему подходу, описанному выше, было предпринято несколько попыток аппроксимировать сопрограммы на C с помощью комбинаций подпрограмм и макросов. Вклад Саймона Тэтэма [35], основанный на устройстве Даффа , является ярким примером этого жанра и является основой для Protothreads и подобных реализаций. [36] В дополнение к возражениям Даффа, [21] собственные комментарии Татхама дают откровенную оценку ограничений этого подхода: «Насколько мне известно, это худшая часть хакерства C, когда-либо встречавшаяся в серьезном производственном коде». [35] Основные недостатки этого приближения заключаются в том, что при отсутствии поддержки отдельного кадра стека для каждой сопрограммы локальные переменные не сохраняются в выходных данных из функции, невозможно иметь несколько записей в функции, и управление может только быть полученным из рутины высшего уровня. [21]
Реализации для C ++
- C ++ сопрограммы TS (техническая спецификация), стандарт для расширений языка C ++ для бесстекового подмножества поведения, подобного сопрограммам, находится в стадии разработки. Visual C ++ и Clang уже поддерживают основные части пространства имен std :: experimental. Техническая спецификация сопрограмм
- Boost.Coroutine - создано : Оливер Kowalke, является официальным выпустила портативный сопрограммная библиотека повышения , начиная с версии 1.53. Библиотека использует Boost.Context и поддерживает ARM, MIPS, PowerPC, SPARC и X86 в POSIX, Mac OS X и Windows.
- Boost.Coroutine2 - также созданный Оливером Ковальке, это модернизированная переносимая библиотека сопрограмм, начиная с версии boost 1.59. Он использует возможности C ++ 11, но исключает поддержку симметричных сопрограмм.
- Мордор - В 2010 году Мози открыл исходный код библиотеки C ++, реализующей сопрограммы, с упором на их использование для абстрагирования асинхронного ввода-вывода в более знакомую последовательную модель. [37]
- CO2 - бесстековая сопрограмма, основанная на трюках препроцессора C ++ , обеспечивающая эмуляцию ожидания / выхода.
- ScummVM - проект ScummVM реализует облегченную версию бесстековых сопрограмм, основанную на статье Саймона Тэтэма .
- tonbit :: coroutine - реализация одиночной асимметричной сопрограммы .h в C ++ 11 через ucontext / fiber
- Сопрограммы появились в Clang в мае 2017 года, реализация libc ++ продолжается. [38]
- elle от Docker
- oatpp-coroutines - сопрограммы без стека с планированием, предназначенные для операций ввода-вывода с высоким уровнем параллелизма. Используется Oat ++ в эксперименте с 5 миллионами соединений WebSocket . Часть веб-фреймворка Oat ++ .
Реализации для C #
- MindTouch Dream - REST-фреймворк MindTouch Dream обеспечивает реализацию сопрограмм на основе шаблона итератора C # 2.0.
- Caliburn - платформа шаблонов экрана Caliburn для WPF использует итераторы C # 2.0 для упрощения программирования пользовательского интерфейса, особенно в асинхронных сценариях.
- Библиотека Power Threading - Библиотека Power Threading от Джеффри Рихтера реализует AsyncEnumerator, который обеспечивает упрощенную модель асинхронного программирования с использованием сопрограмм на основе итераторов.
- Unity Игровой движок реализует сопрограммы.
- Servelat Pieces - проект Servelat Pieces от Евгения Боброва обеспечивает прозрачную асинхронность для служб Silverlight WCF и возможность асинхронно вызывать любой синхронный метод. Реализация основана на блоках итератора Coroutines Caliburn и итератора C #.
- [9] - .NET 2.0+ Framework теперь предоставляет функциональные возможности полупрограмм ( генераторов ) с помощью шаблона итератора и ключевого слова yield.
C # 5.0 включает поддержку синтаксиса ожидания .
Реализации для Clojure
Cloroutine - это сторонняя библиотека, обеспечивающая поддержку бесстековых сопрограмм в Clojure . Он реализован как макрос, статически разделяющий произвольный блок кода на произвольные вызовы var и испускающий сопрограмму как функцию с отслеживанием состояния.
Реализации для D
D реализует сопрограммы в качестве своего стандартного библиотечного класса . Генератор волокна A упрощает предоставление функции волокна в качестве входного диапазона , что делает любое волокно совместимым с существующими алгоритмами диапазонов.
Реализации для Java
Есть несколько реализаций сопрограмм на Java . Несмотря на ограничения, налагаемые абстракциями Java, JVM не исключает такой возможности. [39] Используются четыре общих метода, но два нарушают переносимость байт-кода между совместимыми со стандартами JVM.
- Модифицированные JVM. Можно создать исправленную JVM для более естественной поддержки сопрограмм. Для JVM Da Vinci были созданы исправления. [40]
- Измененный байт-код. Функциональность сопрограмм возможна путем перезаписи обычного байт-кода Java на лету или во время компиляции. Наборы инструментов включают Javaflow , Java Coroutines и Coroutines .
- Механизмы JNI, зависящие от платформы. Они используют методы JNI, реализованные в библиотеках ОС или C, для обеспечения функциональности JVM. [ необходима цитата ]
- Абстракции потоков. Библиотеки сопрограмм, которые реализованы с использованием потоков, могут быть тяжелыми, хотя производительность будет зависеть от реализации потока JVM.
Реализации в JavaScript
- узел-волокна
- Fibjs - fibjs - это среда выполнения JavaScript, построенная на движке Chrome V8 JavaScript. fibjs использует переключение волокон , стиль синхронизации и неблокирующую модель ввода-вывода для создания масштабируемых систем.
- Начиная с ECMAScript 2015 , предоставляются функции безстековых сопрограмм с помощью «генераторов» и выражений yield.
Реализации для Kotlin
Kotlin реализует сопрограммы как часть собственной библиотеки .
Реализации для Модула-2
Modula-2, как определено Wirth, реализует сопрограммы как часть стандартной библиотеки SYSTEM.
Процедура NEWPROCESS () заполняет контекст, заданный блоком кода и пространством для стека в качестве параметров, а процедура TRANSFER () передает управление сопрограмме с учетом контекста сопрограммы в качестве параметра.
Реализация в Mono
Среда выполнения Mono Common Language Runtime поддерживает продолжения, [41] из которых могут быть построены сопрограммы.
Реализация в .NET Framework в виде волокон
Во время разработки .NET Framework 2.0 Microsoft расширила дизайн API-интерфейсов хостинга Common Language Runtime (CLR) для управления планированием на основе волокна с прицелом на его использование в режиме волокна для SQL-сервера. [42] Перед выпуском поддержка ловушки переключения задач ICLRTask :: SwitchOut была удалена из-за нехватки времени. [43] Следовательно, использование Fibre API для переключения задач в настоящее время не является жизнеспособным вариантом в .NET Framework.
Реализации для Perl
- Коро
Сопрограммы изначально реализованы во всех бэкэндах Raku. [44]
Реализации для PHP
- Amphp
- Сопрограмма реализована способом, напоминающим функции Python , и некоторые примеры Go , многие примеры показывают, что код преобразован с тем же количеством строк и поведением.
Реализации для Python
- Python 2.5 реализует лучшую поддержку функций, подобных сопрограммам, на основе расширенных генераторов ( PEP 342 ).
- Python 3.3 улучшает эту возможность, поддерживая делегирование субгенератору ( PEP 380 ).
- Python 3.4 представляет комплексную структуру асинхронного ввода-вывода, стандартизированную в PEP 3156 , которая включает сопрограммы, использующие делегирование субгенератора.
- Python 3.5 представляет явную поддержку сопрограмм с синтаксисом async / await ( PEP 0492 ).
- Начиная с Python 3.7 async / await стали зарезервированными ключевыми словами [10] .
- Eventlet
- Гринлет
- Gevent
- питон без стека
- Заброшенный
- Шрапнель (последний выпуск 2015 г.)
- Камаэлия (последний выпуск 2010 г.)
- cogen (последний выпуск 2009 г.)
- многозадачность (последний выпуск 2007 г.)
- хиральный
Реализации для Ruby
- Ruby 1.9 изначально поддерживает сопрограммы, которые реализованы в виде волокон , которые являются полукорутинами. [45]
- Реализация Марка Де Шемеккера
- Ruby 2.5 и выше изначально поддерживает сопрограммы, которые реализованы как волокна.
- Реализация Томаса Брэнсона
Реализации для Rust
Rust поддерживает сопрограммы начиная с версии 1.39. [46] Есть две популярные библиотеки, обеспечивающие асинхронное время выполнения: tokio и async-std.
Реализации для Scala
Scala Coroutines [47] - это реализация сопрограмм для Scala . Эта реализация представляет собой расширение уровня библиотеки, которое использует макросистему Scala для статического преобразования разделов программы в объекты сопрограмм. Таким образом, эта реализация не требует изменений в JVM, поэтому она полностью переносима между различными JVM и работает с альтернативными серверными модулями Scala, такими как Scala.js , который компилируется в JavaScript. [48]
Scala Coroutines полагаются на coroutine
макрос, который преобразует обычный блок кода в определение сопрограммы. Такое определение сопрограммы может быть вызвано с помощью call
операции, которая создает экземпляр кадра сопрограммы. Кадр сопрограммы может быть возобновлен с помощью resume
метода, который возобновляет выполнение тела сопрограммы до достижения yieldval
ключевого слова, которое приостанавливает кадр сопрограммы. Scala Coroutines также предоставляют snapshot
метод, который эффективно дублирует сопрограмму. [49] Подробное описание сопрограмм Scala со снимками состояния появилось на ECOOP 2018 вместе с их формальной моделью .
Реализации для схемы
Поскольку Scheme обеспечивает полную поддержку продолжений, реализация сопрограмм почти тривиальна, требуя только поддержки очереди продолжений.
Реализации для Smalltalk
Поскольку в большинстве сред Smalltalk стек выполнения является первоклассным гражданином, сопрограммы могут быть реализованы без дополнительной библиотеки или поддержки виртуальных машин.
Реализации для Swift
- SwiftCoroutine - библиотека Swift сопрограмм для iOS, macOS и Linux.
Реализация для языка команд инструментов (Tcl)
Начиная с версии 8.6, язык команд инструментов поддерживает сопрограммы на основном языке. [50]
Реализации для Vala
Vala реализует встроенную поддержку сопрограмм. Они предназначены для использования с основным циклом Gtk, но могут использоваться и отдельно, если позаботиться о том, чтобы конечный обратный вызов никогда не нужно было вызывать перед выполнением, по крайней мере, одного yield.
Реализации на языках ассемблера
Машинно-зависимые языки ассемблера часто предоставляют прямые методы для выполнения сопрограмм. Например, в MACRO-11 , ассемблере семейства миникомпьютеров PDP-11 , переключение «классической» сопрограммы осуществляется инструкцией «JSR PC, @ (SP) +», которая переходит на адрес, извлеченный из стек и выталкивает ток ( то есть , что в следующем ) адреса команды в стек. На VAXen (в Macro-32 ) сопоставимая инструкция - "JSB @ (SP) +". Даже на Motorola 6809 есть инструкция «JSR [, S ++]»; обратите внимание на "++", так как 2 байта (адреса) выталкиваются из стека. Эта инструкция часто используется в (стандартном) «мониторе» Assist 09.
Смотрите также
- Асинхронный / ожидание
- Генератор (компьютерное программирование)
- Конвейер (Unix) , своего рода сопрограмма, используемая для обмена данными между программами [51]
- Protothreads , реализация облегченного потока без стека с использованием механизма, подобного сопрограммам.
Рекомендации
- ^ Кнут, Дональд Эрвин (1997). Фундаментальные алгоритмы (PDF) . Искусство программирования. 1 (3-е изд.). Эддисон-Уэсли. Раздел 1.4.5: История и библиография, стр. 229. ISBN 978-0-201-89683-1. Архивировано (PDF) из оригинала 21.10.2019.
- ^ Конвей, Мелвин Э. (июль 1963 г.). "Дизайн разделимого компилятора диаграмм переходов" (PDF) . Коммуникации ACM . ACM. 6 (7): 396–408. DOI : 10.1145 / 366663.366704 . ISSN 0001-0782 . S2CID 10559786 - через цифровую библиотеку ACM.
- ^ а б Кнут, Дональд Эрвин (1997). Фундаментальные алгоритмы . Искусство программирования. 1 (3-е изд.). Эддисон-Уэсли. Раздел 1.4.2: Сопрограммы, стр. 193–200. ISBN 978-0-201-89683-1.
- ^ Перлис, Алан Дж. (Сентябрь 1982 г.). «Эпиграммы по программированию» . Уведомления ACM SIGPLAN . 17 (9): 7–13. DOI : 10.1145 / 947955.1083808 . S2CID 20512767 . Архивировано из оригинала 17 января 1999 г.
6. Симметрия является сложностью уменьшения концепции (CO-процедуры включают в себя подпрограммы); ищи это везде
- ^ Энтони Ральстон (2000). Энциклопедия информатики . Природа Паб. Группа. ISBN 978-1-56159-248-7. Проверено 11 мая 2013 года .
- ^ См., Например, "Справочник по языку Python " https://docs.python.org/reference/expressions.html#yieldexpr 5.2.10. Выражения доходности] ":
" Все это делает функции генератора очень похожими на сопрограммы; они дают несколько иногда у них есть более одной точки входа, и их выполнение может быть приостановлено. Единственное отличие состоит в том, что функция генератора не может контролировать, где должно продолжаться выполнение после завершения; управление всегда передается вызывающей стороне генератора ". - ^ Мерц, Дэвид (1 июля 2002 г.). «Генераторные государственные машины» . Очаровательный питон . IBM developerWorks. Архивировано из оригинального 28 февраля 2009 года . Проверено 2 февраля 2011 года .
- ^ Даль, О.-Дж. и Hoare, CAR (изд.) (1972). «Иерархические программные структуры». Структурированное программирование . Лондон, Великобритания: Academic Press. С. 175–220. ISBN 978-0122005503.CS1 maint: несколько имен: список авторов ( ссылка ) CS1 maint: дополнительный текст: список авторов ( ссылка )
- ^ «Coroutine: типобезопасные сопрограммы, использующие облегченные типы сеансов» .
- ^ «Совместные подпрограммы в Haskell» .
- ^ "Модуль сопрограмм (coroutines.hhf)" . Руководство по стандартной библиотеке HLA .
- ^ «Новое в JavaScript 1.7» .
- ^ «Руководство Джулии - Поток управления - Задачи (также известные как сопрограммы)» .
- ^ «Что нового в Kotlin 1.1» .
- ^ «Справочное руководство по Lua 5.2» . www.lua.org .
- ^ "Python async / await Tutorial" . Злоупотребление стеком . 17 декабря 2015 года.
- ^ «8. Составные операторы - документация Python 3.8.0» . docs.python.org .
- ^ «Сбор и / или сопрограммы» . 2012-12-19.
- ^ Маккартни, Дж. «Переосмысление языка компьютерного музыкального программирования: SuperCollider» . Компьютерный музыкальный журнал, 26 (4): 61-68. MIT Press, 2002.
- ^ Реализация сопрограмм для .NET путем упаковки API неуправляемого волокна. Архивировано 7 сентября 2008 г.на Wayback Machine , Аджай Шанкар, журнал MSDN.
- ^ а б в «Сопрограммы на C - мозговой трюк» .
- ^ https://www.gnu.org/software/pth/rse-pmt.ps
- ^ а б "libco" . code.byuu.org .
- ^ "getcontext (3) - справочная страница Linux" . man7.org .
- ^ [1] - Библиотека сопрограмм libtask Расс Кокса для FreeBSD, Linux, Mac OS X и SunOS
- ^ Portable Coroutine Library - библиотека C с использованием средств POSIX / SUSv3
- ^ [2] Архивировано 10 января 2006 г.на Wayback Machine - библиотека Coro Эдгара Тёрнига для x86, Linux и FreeBSD.
- ^ [3] - lthread - это многоядерная / многопоточная библиотека сопрограмм, написанная на C
- ^ «libcoroutine: переносимая реализация сопрограмм» . для FreeBSD, Linux, OS X PPC и x86, SunOS, Symbian и др.
- ^ «libconcurrency - масштабируемая библиотека параллелизма для C» . простая библиотека C для переносимых сопрограмм переключения стека
- ^ "libcoro: C-библиотека, которая переносит сопрограммы (совместная многозадачность)" . используется в качестве основы для модуля Coro perl.
- ^ «RIBS (надежная инфраструктура для серверных систем) версии 2: aolarchive / ribs2» . 13 августа 2019 г. - через GitHub.
- ^ "libdill" . libdill.org .
- ^ "Молниеносно быстрая и легкая библиотека асимметричных сопрограмм C 💎 ⛅🚀⛅🌞: hnes / libaco" . 21 октября 2019 г. - через GitHub.
- ^ а б Саймон Татхам (2000). «Сопрограммы на C» .
- ^ «Реализация бесстековой сопрограммы на C и C ++: jsseldenthuis / coroutine» . 18 марта 2019 г. - через GitHub.
- ^ [4] - Открытый исходный код и Mozy: дебют кода Mozy
- ^ [5] - EricWF: Сопрограммы теперь находятся в Clang Trunk! Сейчас работаем над реализацией Libc ++.
- ^ Лукас Стадлер (2009). "Продолжение JVM" (PDF) . Языковой саммит JVM.
- ^ Реми Форакс (19 ноября 2009 г.). «Святая чушь: в JVM есть сопрограмма / продолжение / волокно и т . Д.» . Архивировано из оригинала 19 марта 2015 года.
- ^ [6] Моно продолжения
- ^ [7] , Крис Брамм , веб-журнал cbrumme
- ^ [8] , Дино Филанд, Блог Дино
- ^ «RFC № 31» .
- ^ "полукорутины" . Архивировано из оригинального 24 -го октября 2007 года.
- ^ https://hub.packtpub.com/rust-1-39-releases-with-stable-version-of-async-await-syntax-better-ergonomics-for-match-guards-attributes-on-function-parameters- и-больше / . Отсутствует или пусто
|title=
( справка ) - ^ «Scala Coroutines» . Буря по дороге . Проверено 28 декабря 2019 .
- ^ Часто задаваемые вопросы по Scala Coroutines
- ^ Снимки Scala Coroutine
- ^ "Справочная страница сопрограмм - Встроенные команды Tcl" . Tcl.tk . Проверено 27 июня 2016 .
- ^ Ричи, Деннис М. (1980). «Эволюция системы разделения времени Unix». Языковой дизайн и методология программирования . Конспект лекций по информатике . 79 . С. 25–35. DOI : 10.1007 / 3-540-09745-7_2 . ISBN 978-3-540-09745-7. S2CID 571269 .
дальнейшее чтение
- Ана Люсия де Моура; Роберто Иерусалимский (2004). «Возвращаясь к сопрограммам». Транзакции ACM по языкам и системам программирования . 31 (2): 1–31. CiteSeerX 10.1.1.58.4017 . DOI : 10.1145 / 1462166.1462167 . S2CID 9918449 .
Внешние ссылки
- Саймон Tatham «s C ориентированных всестороннее введение в сопрограммы
- Страница сопрограмм Softpanorama - содержит обширные ссылки на сопрограммы ассемблера