Как вы реализуете сопрограммы в C ++ - PullRequest
62 голосов
/ 23 сентября 2008

Я сомневаюсь, что это может быть сделано переносимо, но есть ли какие-нибудь решения там? Я думаю, что это можно сделать путем создания альтернативного стека и сброса SP, BP и IP при входе в функцию, а также с помощью команды yield save IP и восстановления SP + BP. Деструкторы и безопасность исключений кажутся хитрыми, но решаемыми.

Это было сделано? Это невозможно?

Ответы [ 17 ]

87 голосов
/ 23 сентября 2008

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

Я бы посмотрел на boost :: coroutine library .

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

18 голосов
/ 23 сентября 2008

В POSIX вы можете использовать процедуры makecontext () / swapcontext () для переносимого переключения контекста выполнения. В Windows вы можете использовать Fibre API. В противном случае все, что вам нужно, это немного кода сборки клея, который переключает контекст машины. Я реализовал сопрограммы как с ASM (для AMD64), так и с swapcontext (); ни один не очень сложен.

15 голосов
/ 25 февраля 2012

для потомков,

Удивительный веб-сайт Дмитрия Вьюкова имеет хитрый трюк, использующий ucontext и setjump для имитации сопрограмм в c ++.

Кроме того, контекстная библиотека Оливера Ковальке была недавно принята в Boost, поэтому мы надеемся, что скоро мы увидим обновленную версию boost.coroutine, которая работает на x86_64.

10 голосов
/ 26 октября 2013

Нет простого способа реализовать сопрограмму. Потому что сама сопрограмма вне абстракции стека C / C ++, как поток. Так что это не может быть поддержано без изменений уровня языка для поддержки.

В настоящее время (C ++ 11) все существующие реализации сопрограмм C ++ основаны на взломе на уровне сборки, который трудно перестраховать и надежно пересекает платформы. Чтобы быть надежным, он должен быть стандартным и обрабатываться компиляторами, а не хакерами.

Существует стандартное предложение - N3708 для этого. Проверьте это, если вам интересно.

7 голосов
/ 23 сентября 2008

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

Это может сделать вещи более ремонтопригодными. Другой разработчик C ++ может не сразу понять сопрограмму, тогда как он может быть более знаком с итератором.

6 голосов
/ 19 февраля 2016

Для тех, кто хочет знать, как они могут использовать сопрограммы в портативном виде в C ++ y̶o̶u̶ ̶w̶i̶l̶l̶ ̶h̶a̶v̶e̶ ̶t̶o̶ ̶w̶a̶i̶t̶ ̶f̶o̶r̶ ̶C̶ + ̶ + ̶1̶7 wait ожидание закончилось (см. Ниже)! Комитет по стандартам работает над этой функцией, см. Документ N3722 . Чтобы подвести итоги текущего проекта статьи, вместо Async и Await ключевые слова будут возобновляемыми и ожидают.

Взгляните на экспериментальную реализацию в Visual Studio 2015, чтобы поиграть с экспериментальной реализацией Microsoft. Похоже, у clang еще есть реализация.

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

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

Обновление: Похоже, реализация сопрограммы намечена для C ++ 20, но была выпущена как техническая спецификация для C ++ 17 ( p0057r2 ). Visual C ++, clang и gcc позволяют вам использовать флаг времени компиляции.

5 голосов
/ 23 сентября 2008

Я не думаю, что есть много полноценных, чистых реализаций в C ++. Одна попытка, которая мне нравится, это библиотека протоколов Адама Данкела .

См. Также Прототипы: упрощение управляемого событиями программирования встроенных систем с ограниченным объемом памяти в цифровой библиотеке ACM и обсуждение в теме Википедии Прототип ,

5 голосов
/ 23 сентября 2008

Имеет ли COROUTINE портативную библиотеку C ++ для последовательности сопрограмм , указывающую вам правильное направление? Это элегантное решение, которое прошло испытание временем ..... ему 9 лет!

В папке DOC находится PDF-файл статьи «Переносимая библиотека C ++ для секвенирования сопрограмм» Келда Хельсгауна, в которой описывается библиотека и приводятся короткие примеры ее использования.

[обновление] Я на самом деле успешно использую его сам. Curiosity одолел меня, поэтому я посмотрел на это решение и обнаружил, что оно хорошо подходит для решения проблемы, над которой я работал в течение некоторого времени!

3 голосов
/ 04 декабря 2015

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

C сопрограмм с использованием устройства Даффа

И, например, вот библиотека telnet, которую я изменил, чтобы использовать сопрограммы вместо fork / threads: Библиотека Telnet cli с использованием сопрограмм

А поскольку стандарт C до C99 по сути является истинным подмножеством C ++, это хорошо работает и в C ++.

3 голосов
/ 21 августа 2012

Новая библиотека Boost.Context была выпущена сегодня с переносимыми функциями для реализации сопрограмм.

...