C++: корутины

Вопросы написания собственного программного кода (на любых языках)

Модератор: Olej

Аватара пользователя
Olej
Писатель
Сообщения: 14939
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

C++: корутины

Непрочитанное сообщение Olej » 21 фев 2021, 23:52

Эта тема "отщепилась" от общей темы C++: параллельность, асинхронность, атомарность, потому что тема корутин сильно интересная и очень новая для C++.

Следующий чрезвычайно интересный вопрос (и новый для C++) - это корутины...

Подробно о корутинах в C++
12 марта 2020
Корутины уже существуют во многих языках программирования, например, в Python или C#. Корутины – это еще один способ создания асинхронного кода.
В зависимости от того, в какой среде они используются, их могут называть:

- Бесстековые корутины
- Стековые корутины
- Зеленые потоки
- Волокна
- Горутины

Хорошая новость: стековые корутины, зеленые потоки, волокна и горутины суть одно и то же (но используются они иногда по-разному). О них мы поговорим ниже в этой статье и будем называть их волокнами или стековыми корутинами. Но у бесстековых корутин есть некоторые особенности, о которых необходимо поговорить отдельно.
Корутины в C++20. Часть 1 +18
26.09.20 10:26
Корутины это функции которые могут приостановить или возобновить свое выполнение при этом сохраняя свое состояние. Эволюция функций в C++ сделала шаг вперед.
Идея корутин, представленная как новая в C++20, довольно стара. Понятие корутины было предложено Мелвином Конвеем. Он использовал данное понятие в публикации о разработке компиляторов от 1963. Дональд Кнут называл процедуры частным случаем корутин. Иногда должно пройти время чтобы та или иная идея была принята.

Посредством новых ключевых слов co_await и co_yield C++20 расширяет понятие выполнения функций в C++ при помощи двух новых концепций.
P.S. Почему возник такой интерес к корутинам? И почему возник только сейчас?
Как я понимаю ситуацию:
- потому что корутины переключают контекст выполнения без вмешательства ядра, без аппаратного переключения контекста процессора как у thread...
- и происходить это может намного (на порядок) быстрее...
- и особенно показала это организация параллелизма в языке Go, его горутины, которые во многом реализуются как корутины, переключаемые а пространстве пользователя.

P.P.S. О механизме планирования Go я как-то перевёл статью для сайта Go, вот здесь - Диспетчер Go
Перевод статьи "The Go scheduler" от Daniel Morsing.
Оригинал здесь: The Go scheduler
30 JUNE 2013
Потоки имеют свою собственную сигнальную маску, могут быть прикреплены к процессорам с помощью аффинити маски, могут быть введены в группы, и могут быть тестированы на предмет того какие ресурсы они используют. Все эти элементы добавляют накладные расходы для объектов, а, поскольку они просто не нужны для Go программ использующих Go-рутины, эти накладные расходы лавинно складываются, когда у вас становится 100000 потоков в вашей программе.

Аватара пользователя
Olej
Писатель
Сообщения: 14939
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: C++: корутины

Непрочитанное сообщение Olej » 22 фев 2021, 02:28

Olej писал(а):
21 фев 2021, 23:52
P.P.S. О механизме планирования Go я как-то перевёл статью для сайта Go, вот здесь - Диспетчер Go
Но поскольку все эти юные начинающие Go-активисты - прыщавые придурки пубертатного периода :lol: , которым главнейшее себя показать, а не материал достоверно выставить, то там в их "изложении" - полная херня, с потерянными иллюстрациями...
В связи с чем я просто приложу сюда свой перевод (правленный).
Вложения
Go_scheduler.odt
(212.41 КБ) 20 скачиваний

Аватара пользователя
Olej
Писатель
Сообщения: 14939
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

C++: корутины

Непрочитанное сообщение Olej » 22 фев 2021, 14:57

Olej писал(а):
21 фев 2021, 23:52
Хорошая новость: стековые корутины, зеленые потоки, волокна и горутины суть одно и то же (но используются они иногда по-разному). О них мы поговорим ниже в этой статье и будем называть их волокнами или стековыми корутинами. Но у бесстековых корутин есть некоторые особенности, о которых необходимо поговорить отдельно.
Всё, что есть стековые корутины, реализуемо в качестве библиотек и соответствующих API.
Некоторые варианты тому предоставляет Boost:

Chapter 1. Coroutine

Код: Выделить всё

olej@nvme:~$ aptitude search boost-coroutine
p   libboost-coroutine-dev                                                                    - provides a sort of cooperative multitasking on a single thread (default version)                    
p   libboost-coroutine-dev:i386                                                               - provides a sort of cooperative multitasking on a single thread (default version)                    
p   libboost-coroutine1.67-dev                                                                - provides a sort of cooperative multitasking on a single thread                                      
p   libboost-coroutine1.67.0                                                                  - provides a sort of cooperative multitasking on a single thread                                      
p   libboost-coroutine1.71-dev                                                                - provides a sort of cooperative multitasking on a single thread                                      
p   libboost-coroutine1.71-dev:i386                                                           - provides a sort of cooperative multitasking on a single thread                                      
p   libboost-coroutine1.71.0                                                                  - provides a sort of cooperative multitasking on a single thread                                      
p   libboost-coroutine1.71.0:i386                                                             - provides a sort of cooperative multitasking on a single thread  

Код: Выделить всё

olej@nvme:~$ aptitude show libboost-coroutine-dev
Пакет: libboost-coroutine-dev                    
Версия: 1.71.0.0ubuntu2
Состояние: не установлен
Мультиархитектура: такая же
Приоритет: необязательный
Раздел: universe/libdevel
Сопровождающий: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Архитектура: amd64
Размер в распакованном виде: 10,2 k
Зависит: libboost-coroutine1.71-dev
Ломает: libboost-coroutine-dev:i386 (!= 1.71.0.0ubuntu2)
Заменяет: libboost-coroutine-dev:i386 (< 1.71.0.0ubuntu2)
Описание: provides a sort of cooperative multitasking on a single thread (default version)
 Данный пакет является частью набора C++ библиотек Boost. 
 
 Boost.Coroutine provides templates for generalized subroutines which allow multiple entry points for suspending and resuming execution at certain locations. It preserves the local state of
 execution and allows re- entering subroutines more than once (useful if state must be kept across function calls). 
 
 Coroutines can be viewed as a language-level construct providing a special kind of control flow. 
 
 In contrast to threads, which are pre-emptive, coroutine switches are cooperative (programmer controls when a switch will happen). The kernel is not involved in the coroutine switches. 
 
 The implementation uses Boost.Context for context switching. 
 
 This package is a dependency package, which depends on Debian's default Boost version (currently 1.71).
Домашняя страница: http://www.boost.org/libs/coroutine/
Chapter 1. Fiber

Код: Выделить всё

olej@nvme:~$ aptitude search boost-fiber
p   libboost-fiber-dev                                                                        - cooperatively-scheduled micro-/userland-threads (default version)                                   
p   libboost-fiber-dev:i386                                                                   - cooperatively-scheduled micro-/userland-threads (default version)                                   
p   libboost-fiber1.67-dev                                                                    - cooperatively-scheduled micro-/userland-threads                                                     
p   libboost-fiber1.67.0                                                                      - cooperatively-scheduled micro-/userland-threads                                                     
p   libboost-fiber1.71-dev                                                                    - cooperatively-scheduled micro-/userland-threads                                                     
p   libboost-fiber1.71-dev:i386                                                               - cooperatively-scheduled micro-/userland-threads                                                     
p   libboost-fiber1.71.0                                                                      - cooperatively-scheduled micro-/userland-threads                                                     
p   libboost-fiber1.71.0:i386                                                                 - cooperatively-scheduled micro-/userland-threads             

Код: Выделить всё

olej@nvme:~$ aptitude show libboost-fiber-dev
Пакет: libboost-fiber-dev                        
Версия: 1.71.0.0ubuntu2
Состояние: не установлен
Мультиархитектура: такая же
Приоритет: необязательный
Раздел: universe/libdevel
Сопровождающий: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Архитектура: amd64
Размер в распакованном виде: 10,2 k
Зависит: libboost-fiber1.71-dev
Ломает: libboost-fiber-dev:i386 (!= 1.71.0.0ubuntu2)
Заменяет: libboost-fiber-dev:i386 (< 1.71.0.0ubuntu2)
Описание: cooperatively-scheduled micro-/userland-threads (default version)
 Данный пакет является частью набора C++ библиотек Boost. 
 
 Boost.Fiber provides a framework for micro-/userland-threads (fibers) scheduled cooperatively.  The API contains classes and functions to manage and synchronize fibers similarly to standard
 thread support library. 
 
 Each fiber has its own stack. 
 
 A fiber can save the current execution state, including all registers and CPU flags, the instruction pointer, and the stack pointer and later restore this state. The idea is to have multiple
 execution paths running on a single thread using cooperative scheduling (versus threads, which are preemptively scheduled). The running fiber decides explicitly when it should yield to allow
 another fiber to run (context switching). Boost.Fiber internally uses execution_context from Boost.Context; the classes in this library manage, schedule and, when needed, synchronize those
 execution contexts. A context switch between threads usually costs thousands of CPU cycles on x86, compared to a fiber switch with less than a hundred cycles. A fiber runs on a single thread at
 any point in time. 
 
 This package is a dependency package, which depends on Debian's default Boost version (currently 1.71).
Домашняя страница: http://www.boost.org/libs/fiber/
P.S. Обращаем внимание: эти 2 пакета корутин устанавливаем из стандартного репозитория дистрибутива, более свежие версии можем установить из http://www.boost.org

Аватара пользователя
Olej
Писатель
Сообщения: 14939
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: C++: корутины

Непрочитанное сообщение Olej » 22 фев 2021, 15:16

Olej писал(а):
21 фев 2021, 23:52
- и происходить это может намного (на порядок) быстрее...
Для тех задач, областей применения, когда точки переключения параллельностей (активностей) строго детерминированы, скорость переключения контекстов корутин ожидаемо должна быть на порядки быстрее, чем традиционных потоков - переключение происходит в user space без перехода в режим ядра.

Есть такой тест (для разных языков, их механизмов и т.д.) Skynet 1M concurrency microbenchmark
Создает активность (горутину, что угодно), которая порождает 10 новых активностей, каждая из них порождает еще 10 активностей и т. Д., Пока на последнем уровне не будет создан миллион активностей. Затем каждая из них возвращает свой порядковый номер (от 0 до 999999), который суммируется на предыдущем уровне и отправляется обратно вверх по потоку, пока не достигнет корневой активности. (Ответ должен быть 499999500000).
Olej писал(а):
22 фев 2021, 14:57
Chapter 1. Fiber
Для Boost::fiber они дают разительные результаты (Performance): скорость, для разных вариантов fiber, выше от 25-50 до 500-1000 раз чем: pthread, std::thread, std::async

Аватара пользователя
Olej
Писатель
Сообщения: 14939
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: C++: корутины

Непрочитанное сообщение Olej » 22 фев 2021, 19:41

Olej писал(а):
22 фев 2021, 14:57
Всё, что есть стековые корутины, реализуемо в качестве библиотек и соответствующих API.
Некоторые варианты тому предоставляет Boost:
Как легко прогнозировать, установка корутин из Boost потребует довольно много базовых проектов из Boost:

Код: Выделить всё

olej@nvme:~$ sudo apt install libboost-fiber-dev
[sudo] пароль для olej:       
Чтение списков пакетов… Готово
Построение дерева зависимостей       
Чтение информации о состоянии… Готово
Будут установлены следующие дополнительные пакеты:
  libboost-atomic1.71-dev libboost-atomic1.71.0 libboost-chrono1.71-dev libboost-chrono1.71.0 libboost-context1.71-dev libboost-context1.71.0 libboost-date-time1.71-dev libboost-fiber1.71-dev
  libboost-fiber1.71.0 libboost-filesystem1.71-dev libboost-serialization1.71-dev libboost-serialization1.71.0 libboost-system1.71-dev libboost-system1.71.0 libboost-thread1.71-dev
  libboost1.71-dev
Предлагаемые пакеты:
  libboost1.71-doc libboost-container1.71-dev libboost-contract1.71-dev libboost-coroutine1.71-dev libboost-exception1.71-dev libboost-graph1.71-dev libboost-graph-parallel1.71-dev
  libboost-iostreams1.71-dev libboost-locale1.71-dev libboost-log1.71-dev libboost-math1.71-dev libboost-mpi1.71-dev libboost-mpi-python1.71-dev libboost-numpy1.71-dev
  libboost-program-options1.71-dev libboost-python1.71-dev libboost-random1.71-dev libboost-regex1.71-dev libboost-stacktrace1.71-dev libboost-test1.71-dev libboost-timer1.71-dev
  libboost-type-erasure1.71-dev libboost-wave1.71-dev libboost1.71-tools-dev libmpfrc++-dev libntl-dev
Следующие НОВЫЕ пакеты будут установлены:
  libboost-atomic1.71-dev libboost-atomic1.71.0 libboost-chrono1.71-dev libboost-chrono1.71.0 libboost-context1.71-dev libboost-context1.71.0 libboost-date-time1.71-dev libboost-fiber-dev
  libboost-fiber1.71-dev libboost-fiber1.71.0 libboost-filesystem1.71-dev libboost-serialization1.71-dev libboost-serialization1.71.0 libboost-system1.71-dev libboost-system1.71.0
  libboost-thread1.71-dev libboost1.71-dev
Обновлено 0 пакетов, установлено 17 новых пакетов, для удаления отмечено 0 пакетов, и 0 пакетов не обновлено.
Необходимо скачать 12,6 MB архивов.
После данной операции объём занятого дискового пространства возрастёт на 173 MB.
Хотите продолжить? [Д/н] y
Пол:1 http://archive.ubuntu.com/ubuntu focal/main amd64 libboost1.71-dev amd64 1.71.0-6ubuntu6 [9.068 kB]
Пол:2 http://archive.ubuntu.com/ubuntu focal/main amd64 libboost-atomic1.71.0 amd64 1.71.0-6ubuntu6 [205 kB]
Пол:3 http://archive.ubuntu.com/ubuntu focal/main amd64 libboost-atomic1.71-dev amd64 1.71.0-6ubuntu6 [205 kB]
Пол:4 http://archive.ubuntu.com/ubuntu focal/main amd64 libboost-chrono1.71.0 amd64 1.71.0-6ubuntu6 [217 kB]
Пол:5 http://archive.ubuntu.com/ubuntu focal/main amd64 libboost-chrono1.71-dev amd64 1.71.0-6ubuntu6 [225 kB]
Пол:6 http://archive.ubuntu.com/ubuntu focal/main amd64 libboost-serialization1.71.0 amd64 1.71.0-6ubuntu6 [302 kB]
Пол:7 http://archive.ubuntu.com/ubuntu focal/main amd64 libboost-serialization1.71-dev amd64 1.71.0-6ubuntu6 [344 kB]
Пол:8 http://archive.ubuntu.com/ubuntu focal/main amd64 libboost-date-time1.71-dev amd64 1.71.0-6ubuntu6 [228 kB]
Пол:9 http://archive.ubuntu.com/ubuntu focal/main amd64 libboost-system1.71.0 amd64 1.71.0-6ubuntu6 [205 kB]
Пол:10 http://archive.ubuntu.com/ubuntu focal/main amd64 libboost-system1.71-dev amd64 1.71.0-6ubuntu6 [205 kB]
Пол:11 http://archive.ubuntu.com/ubuntu focal/main amd64 libboost-thread1.71-dev amd64 1.71.0-6ubuntu6 [258 kB]
Пол:12 http://archive.ubuntu.com/ubuntu focal/main amd64 libboost-context1.71.0 amd64 1.71.0-6ubuntu6 [207 kB]
Пол:13 http://archive.ubuntu.com/ubuntu focal/universe amd64 libboost-context1.71-dev amd64 1.71.0-6ubuntu6 [208 kB]
Пол:14 http://archive.ubuntu.com/ubuntu focal/main amd64 libboost-filesystem1.71-dev amd64 1.71.0-6ubuntu6 [258 kB]
Пол:15 http://archive.ubuntu.com/ubuntu focal/universe amd64 libboost-fiber1.71.0 amd64 1.71.0-6ubuntu6 [226 kB]
Пол:16 http://archive.ubuntu.com/ubuntu focal/universe amd64 libboost-fiber1.71-dev amd64 1.71.0-6ubuntu6 [237 kB]
Пол:17 http://archive.ubuntu.com/ubuntu focal/universe amd64 libboost-fiber-dev amd64 1.71.0.0ubuntu2 [3.824 B]
Получено 12,6 MB за 4с (2.804 kB/s)             
Выбор ранее не выбранного пакета libboost1.71-dev:amd64.
(Чтение базы данных … на данный момент установлено 374273 файла и каталога.)
Подготовка к распаковке …/00-libboost1.71-dev_1.71.0-6ubuntu6_amd64.deb …
Распаковывается libboost1.71-dev:amd64 (1.71.0-6ubuntu6) …
Выбор ранее не выбранного пакета libboost-atomic1.71.0:amd64.
Подготовка к распаковке …/01-libboost-atomic1.71.0_1.71.0-6ubuntu6_amd64.deb …
Распаковывается libboost-atomic1.71.0:amd64 (1.71.0-6ubuntu6) …
Выбор ранее не выбранного пакета libboost-atomic1.71-dev:amd64.
Подготовка к распаковке …/02-libboost-atomic1.71-dev_1.71.0-6ubuntu6_amd64.deb …
Распаковывается libboost-atomic1.71-dev:amd64 (1.71.0-6ubuntu6) …
Выбор ранее не выбранного пакета libboost-chrono1.71.0:amd64.
Подготовка к распаковке …/03-libboost-chrono1.71.0_1.71.0-6ubuntu6_amd64.deb …
Распаковывается libboost-chrono1.71.0:amd64 (1.71.0-6ubuntu6) …
Выбор ранее не выбранного пакета libboost-chrono1.71-dev:amd64.
Подготовка к распаковке …/04-libboost-chrono1.71-dev_1.71.0-6ubuntu6_amd64.deb …
Распаковывается libboost-chrono1.71-dev:amd64 (1.71.0-6ubuntu6) …
Выбор ранее не выбранного пакета libboost-serialization1.71.0:amd64.
Подготовка к распаковке …/05-libboost-serialization1.71.0_1.71.0-6ubuntu6_amd64.deb …
Распаковывается libboost-serialization1.71.0:amd64 (1.71.0-6ubuntu6) …
Выбор ранее не выбранного пакета libboost-serialization1.71-dev:amd64.
Подготовка к распаковке …/06-libboost-serialization1.71-dev_1.71.0-6ubuntu6_amd64.deb …
Распаковывается libboost-serialization1.71-dev:amd64 (1.71.0-6ubuntu6) …
Выбор ранее не выбранного пакета libboost-date-time1.71-dev:amd64.
Подготовка к распаковке …/07-libboost-date-time1.71-dev_1.71.0-6ubuntu6_amd64.deb …
Распаковывается libboost-date-time1.71-dev:amd64 (1.71.0-6ubuntu6) …
Выбор ранее не выбранного пакета libboost-system1.71.0:amd64.
Подготовка к распаковке …/08-libboost-system1.71.0_1.71.0-6ubuntu6_amd64.deb …
Распаковывается libboost-system1.71.0:amd64 (1.71.0-6ubuntu6) …
Выбор ранее не выбранного пакета libboost-system1.71-dev:amd64.
Подготовка к распаковке …/09-libboost-system1.71-dev_1.71.0-6ubuntu6_amd64.deb …
Распаковывается libboost-system1.71-dev:amd64 (1.71.0-6ubuntu6) …
Выбор ранее не выбранного пакета libboost-thread1.71-dev:amd64.
Подготовка к распаковке …/10-libboost-thread1.71-dev_1.71.0-6ubuntu6_amd64.deb …
Распаковывается libboost-thread1.71-dev:amd64 (1.71.0-6ubuntu6) …
Выбор ранее не выбранного пакета libboost-context1.71.0:amd64.
Подготовка к распаковке …/11-libboost-context1.71.0_1.71.0-6ubuntu6_amd64.deb …
Распаковывается libboost-context1.71.0:amd64 (1.71.0-6ubuntu6) …
Выбор ранее не выбранного пакета libboost-context1.71-dev:amd64.
Подготовка к распаковке …/12-libboost-context1.71-dev_1.71.0-6ubuntu6_amd64.deb …
Распаковывается libboost-context1.71-dev:amd64 (1.71.0-6ubuntu6) …
Выбор ранее не выбранного пакета libboost-filesystem1.71-dev:amd64.
Подготовка к распаковке …/13-libboost-filesystem1.71-dev_1.71.0-6ubuntu6_amd64.deb …
Распаковывается libboost-filesystem1.71-dev:amd64 (1.71.0-6ubuntu6) …
Выбор ранее не выбранного пакета libboost-fiber1.71.0:amd64.
Подготовка к распаковке …/14-libboost-fiber1.71.0_1.71.0-6ubuntu6_amd64.deb …
Распаковывается libboost-fiber1.71.0:amd64 (1.71.0-6ubuntu6) …
Выбор ранее не выбранного пакета libboost-fiber1.71-dev:amd64.
Подготовка к распаковке …/15-libboost-fiber1.71-dev_1.71.0-6ubuntu6_amd64.deb …
Распаковывается libboost-fiber1.71-dev:amd64 (1.71.0-6ubuntu6) …
Выбор ранее не выбранного пакета libboost-fiber-dev:amd64.
Подготовка к распаковке …/16-libboost-fiber-dev_1.71.0.0ubuntu2_amd64.deb …
Распаковывается libboost-fiber-dev:amd64 (1.71.0.0ubuntu2) …
Настраивается пакет libboost1.71-dev:amd64 (1.71.0-6ubuntu6) …
Настраивается пакет libboost-chrono1.71.0:amd64 (1.71.0-6ubuntu6) …
Настраивается пакет libboost-atomic1.71.0:amd64 (1.71.0-6ubuntu6) …
Настраивается пакет libboost-context1.71.0:amd64 (1.71.0-6ubuntu6) …
Настраивается пакет libboost-serialization1.71.0:amd64 (1.71.0-6ubuntu6) …
Настраивается пакет libboost-system1.71.0:amd64 (1.71.0-6ubuntu6) …
Настраивается пакет libboost-atomic1.71-dev:amd64 (1.71.0-6ubuntu6) …
Настраивается пакет libboost-fiber1.71.0:amd64 (1.71.0-6ubuntu6) …
Настраивается пакет libboost-chrono1.71-dev:amd64 (1.71.0-6ubuntu6) …
Настраивается пакет libboost-system1.71-dev:amd64 (1.71.0-6ubuntu6) …
Настраивается пакет libboost-filesystem1.71-dev:amd64 (1.71.0-6ubuntu6) …
Настраивается пакет libboost-serialization1.71-dev:amd64 (1.71.0-6ubuntu6) …
Настраивается пакет libboost-date-time1.71-dev:amd64 (1.71.0-6ubuntu6) …
Настраивается пакет libboost-thread1.71-dev:amd64 (1.71.0-6ubuntu6) …
Настраивается пакет libboost-context1.71-dev:amd64 (1.71.0-6ubuntu6) …
Настраивается пакет libboost-fiber1.71-dev:amd64 (1.71.0-6ubuntu6) …
Настраивается пакет libboost-fiber-dev:amd64 (1.71.0.0ubuntu2) …
Обрабатываются триггеры для libc-bin (2.31-0ubuntu9.2) …

Код: Выделить всё

olej@nvme:~$ sudo apt install libboost-coroutine-dev
Чтение списков пакетов… Готово
Построение дерева зависимостей       
Чтение информации о состоянии… Готово
Будут установлены следующие дополнительные пакеты:
  libboost-coroutine1.71-dev libboost-coroutine1.71.0
Следующие НОВЫЕ пакеты будут установлены:
  libboost-coroutine-dev libboost-coroutine1.71-dev libboost-coroutine1.71.0
Обновлено 0 пакетов, установлено 3 новых пакетов, для удаления отмечено 0 пакетов, и 0 пакетов не обновлено.
Необходимо скачать 449 kB архивов.
После данной операции объём занятого дискового пространства возрастёт на 4.302 kB.
Хотите продолжить? [Д/н] y
Пол:1 http://archive.ubuntu.com/ubuntu focal/universe amd64 libboost-coroutine1.71.0 amd64 1.71.0-6ubuntu6 [219 kB]
Пол:2 http://archive.ubuntu.com/ubuntu focal/universe amd64 libboost-coroutine1.71-dev amd64 1.71.0-6ubuntu6 [227 kB]
Пол:3 http://archive.ubuntu.com/ubuntu focal/universe amd64 libboost-coroutine-dev amd64 1.71.0.0ubuntu2 [3.660 B]
Получено 449 kB за 1с (859 kB/s)             
Выбор ранее не выбранного пакета libboost-coroutine1.71.0:amd64.
(Чтение базы данных … на данный момент установлен 389591 файл и каталог.)
Подготовка к распаковке …/libboost-coroutine1.71.0_1.71.0-6ubuntu6_amd64.deb …
Распаковывается libboost-coroutine1.71.0:amd64 (1.71.0-6ubuntu6) …
Выбор ранее не выбранного пакета libboost-coroutine1.71-dev:amd64.
Подготовка к распаковке …/libboost-coroutine1.71-dev_1.71.0-6ubuntu6_amd64.deb …
Распаковывается libboost-coroutine1.71-dev:amd64 (1.71.0-6ubuntu6) …
Выбор ранее не выбранного пакета libboost-coroutine-dev:amd64.
Подготовка к распаковке …/libboost-coroutine-dev_1.71.0.0ubuntu2_amd64.deb …
Распаковывается libboost-coroutine-dev:amd64 (1.71.0.0ubuntu2) …
Настраивается пакет libboost-coroutine1.71.0:amd64 (1.71.0-6ubuntu6) …
Настраивается пакет libboost-coroutine1.71-dev:amd64 (1.71.0-6ubuntu6) …
Настраивается пакет libboost-coroutine-dev:amd64 (1.71.0.0ubuntu2) …
Обрабатываются триггеры для libc-bin (2.31-0ubuntu9.2) …

Аватара пользователя
Olej
Писатель
Сообщения: 14939
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: C++: корутины

Непрочитанное сообщение Olej » 22 фев 2021, 20:30

Olej писал(а):
22 фев 2021, 19:41
Как легко прогнозировать, установка корутин из Boost потребует довольно много базовых проектов из Boost:
Простейший пример использования boost::fibers - только "синтаксический сахар":

Код: Выделить всё

#include <cstdlib>
#include <iostream>
#include <boost/fiber/all.hpp>

// https://habr.com/ru/company/piter/blog/491996/

auto fn = [](std::string const& str, int n)->void {
     for ( int i = 0; i < n; ++i) {
          std::cout << i << ": " << str << std::endl;
               boost::this_fiber::yield();
     }
};

int main() {
     try {
          boost::fibers::fiber f1( fn, "abc", 5);
          std::cerr << "f1 : " << f1.get_id() << std::endl;
          f1.join();
          std::cout << "done." << std::endl;
          return EXIT_SUCCESS;
     } catch ( std::exception const& e) {
          std::cerr << "exception: " << e.what() << std::endl;
     } catch (...) {
          std::cerr << "unhandled exception" << std::endl;
     }
     return EXIT_FAILURE;
}

Код: Выделить всё

olej@nvme:~/2021/OWN_TEST.codes/coroutine$ make
g++ -Wall -pthread -pedantic -std=c++17 fiber1.cc -o fiber1 -lboost_fiber -lboost_context

Код: Выделить всё

olej@nvme:~/2021/OWN_TEST.codes/coroutine$ ./fiber1 
f1 : 0x7fadae5c5f00
0: abc
1: abc
2: abc
3: abc
4: abc
done.
Вложения
fiber1.cc
(770 байт) 19 скачиваний

Аватара пользователя
Olej
Писатель
Сообщения: 14939
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: C++: корутины

Непрочитанное сообщение Olej » 23 фев 2021, 22:21

Olej писал(а):
22 фев 2021, 20:30
Простейший пример использования boost::fibers - только "синтаксический сахар":
Огромное множество примеров кода с boost::fibers находим непосредственно на GIT-репозитории проекта: boostorg/fiber

Аватара пользователя
Olej
Писатель
Сообщения: 14939
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: C++: корутины

Непрочитанное сообщение Olej » 23 фев 2021, 22:59

Olej писал(а):
22 фев 2021, 20:30
Простейший пример использования boost::fibers - только "синтаксический сахар":
Столь же простой (а то и ещё проще) пример использования boost::coroutine - я нашёл в очень интересной и столь же короткой заметке: Boost.Coroutine.
А "синтаксический сахар", с которого нужно начать и в одном и другом случае - это потому, что нужно прежде установить опции компилятора, а ещё более компоновщика - библиотеки - для сборки таких приложений, для написания Makefile...
Вот этот код:

Код: Выделить всё

#include <boost/coroutine/all.hpp>
#include <iostream>

using namespace boost::coroutines;

// https://github.com/igor-dyrov/Boost.Coroutine

void cooperative(coroutine<void>::push_type &sink)
{
  std::cout << "Hello";
  sink();
  std::cout << "world";
}

int main()
{
  coroutine<void>::pull_type source{cooperative};
  std::cout << ", ";
  source();
  std::cout << "!\n";
}
А Makefile для 2-х групп проектов:

Код: Выделить всё

CXX += -Wall -pthread -pedantic -std=c++17

TASK = fiber1 corout1
all: $(TASK)

fiber%: fiber%.cc
        $(CXX) $< -o $@ -lboost_fiber -lboost_context

corout%: corout%.cc
        $(CXX) $< -o $@ -lboost_coroutine -lboost_context
Выполняем:

Код: Выделить всё

olej@nvme:~/2021/OWN_TEST.codes/coroutine$ make
g++ -Wall -pthread -pedantic -std=c++17 corout1.cc -o corout1 -lboost_coroutine -lboost_context

olej@nvme:~/2021/OWN_TEST.codes/coroutine$ ./corout1
Hello, world!
Это реализация того что называется асимметричными корутинами (pull_type + push_type): прерываясь корутина передаёт управление в ту точку, откуда его сама получила.
Вложения
corout1.cc
(376 байт) 23 скачивания

Аватара пользователя
Olej
Писатель
Сообщения: 14939
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: C++: корутины

Непрочитанное сообщение Olej » 23 фев 2021, 23:14

Olej писал(а):
23 фев 2021, 22:21
Огромное множество примеров кода с boost::fibers находим непосредственно на GIT-репозитории проекта: boostorg/fiber
Точно так же, страницу проекта мы находим в Boost: boost.coroutine ... там и код тестов, и документация.
Но там же читаем (перевод мой):
Обратите внимание, что boost.coroutine устарел - boost.coroutine2 является его преемником. Если же вы вынуждены использовать компилятор до C ++ 11, то вам все равно следует использовать boost.coroutine.

И соответственно boost.coroutine2
boost.coroutine2 требует C ++ 11! Обратите внимание, что boost.coroutine2 является преемником устаревшей boost.coroutine.

Аватара пользователя
Olej
Писатель
Сообщения: 14939
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: C++: корутины

Непрочитанное сообщение Olej » 25 фев 2021, 18:36

Olej писал(а):
23 фев 2021, 22:59
Столь же простой (а то и ещё проще) пример использования boost::coroutine - я нашёл в очень интересной и столь же короткой заметке: Boost.Coroutine.
Но это тот вид boost::coroutine, который его автор Oliver Kowalke называет asymmetric_coroutine, а ещё там же есть другая модификация symmetric_coroutine - Chapter 1. Coroutine

Код: Выделить всё

Table of Contents

Overview
Introduction
Motivation
Coroutine
	Asymmetric coroutine
		Class asymmetric_coroutine<>::pull_type
		Class asymmetric_coroutine<>::push_type
	Symmetric coroutine
		Class symmetric_coroutine<>::call_type
		Class symmetric_coroutine<>::yield_type
Attributes
Stack allocation
	Class protected_stack_allocator
	Class standard_stack_allocator
	Class segmented_stack_allocator
	Class stack_traits
	Class stack_context
	Support for valgrind
Performance
Architectures
Acknowledgments
Относительно симметричных корутин пишут что они "делегируют последующее выполнение другой корутине", т.е. могут передавать управление по кругу друг другу.

Ответить

Вернуться в «Программирование»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 2 гостя