#c #c 20 #c -standard-library #c -coroutine
#c #c 20 #c -стандартная библиотека #c -сопрограмма #c -сопрограмма
Вопрос:
Этот вопрос на самом деле состоит из двух вопросов. Я спрошу их сразу, потому что они могут быть связаны.
Я только что впервые взглянул на сопрограммы C 20. Если вы видели различные примеры, большинство из них довольно простые. Например, следующее:
generator<int> ints(int x)
{
for (int i = 0; i < x; i)
{
co_yield i;
}
}
Во всех примерах используется специальный возвращаемый тип, который, очевидно, содержит результат вычисления плюс контекст сопрограммы. Однако ни в одном примере не используется стандартный возвращаемый тип. Они либо незаметно опускают этот тип, либо определяют пользовательский вложенный класс, который трудно понять (для меня, в настоящее время).
1. Означает ли это, что стандартная библиотека C 20 не предоставляет типы возвращаемых сопрограмм, которые готовы к использованию, например, для генератора?
Лучшее, что я смог найти std::coroutine_handle
, это то, что внутренне используется упомянутыми пользовательскими классами.
В документах говорится, что сопрограммы являются хорошим инструментом для реализации алгоритмов, которые требуют поэтапной обработки данных и обычно должны быть разделены на фрагменты, например, с использованием (потенциально ужасно сложного) механизма состояний. Я тоже это понимаю. Я даже помню какой-то проект, который был бы отличным вариантом использования для сопрограммы, а именно загрузка большого сложного XML-файла с использованием потокового интерфейса.
Тем не менее, кажется, есть большая разница: при реализации механизма состояний довольно легко сохранять и загружать состояние на / с диска, поскольку все данные о состоянии доступны как стандартные переменные (достаточно некоторой проверки ошибок и обработки файлов). Я думаю о чем-то вроде пользовательского интерфейса для отмены / возобновления длительных вычислений.
2. Существует ли (простой) способ сохранения / загрузки контекста сопрограммы в / из постоянного хранилища? Есть ли что-нибудь в стандарте C 20, что помогает в этом?
Ответ №1:
- Означает ли это, что стандартная библиотека C 20 не предоставляет типы возвращаемых сопрограмм, которые готовы к использованию, например, для генератора?
Это не так. В то время как в технической спецификации предлагались все основные положения о том, как вы можете сделать тип совместимым с сопрограммой, ни в ней, ни в какой-либо из ее редакций не предлагались какие-либо стандартные типы, совместимые с сопрограммой.
Он предоставил по крайней мере одну игрушечную реализацию генератора, которую можно было бы использовать с небольшой настройкой.
p2168 формально предлагает std::generator
тип, который будет использоваться в сопрограммах. Вы также можете ознакомиться с библиотекой cppcoro Льюиса Бейкера.
- Существует ли (простой) способ сохранения / загрузки контекста сопрограммы в / из постоянного хранилища?
Короткий ответ — «нет».
Есть ли что-нибудь в стандарте C 20, что помогает в этом?
Короткий ответ также «нет».
Когда сопрограмма создается, компилятор выделяет некоторое пространство в куче для контекста сопрограммы, включая локальные переменные и копии / ссылки на параметры. Не совсем в отличие от того, как существуют стековые фреймы для вызовов функций. Но мы же не сериализуем фреймы стека, не так ли? Это не совсем имеет смысл.
Подумайте об этом так: если бы вы хотели сериализовать обычную функцию, вы бы превратили ее в объект. Как это делает шаблон команды. Результат не совсем похож на фрейм стека, но у вас все равно есть что-то для вызова, что делает то, что вам нужно.
Сопрограммы ничем не отличаются. Если вам нужно сериализовать / десериализовать состояние, вы должны использовать вызываемый объект. Вы могли бы использовать этот объект внутри сопрограммы, но это было бы не совсем то же самое.
Ответ №2:
В C 20 нет библиотечных функций или типов сопрограмм, за исключением дескрипторов и признаков на уровне реализации. Вам нужна библиотека сопрограмм, которую вы можете создать самостоятельно или использовать из существующего источника, такого как cppcoro.
Нет поддержки для сохранения контекста сопрограммы в постоянное хранилище. Вам придется создавать это самостоятельно. Вероятно, это будет иметь довольно сложную реализацию.
Комментарии:
1. Я не уверен, что на самом деле возможно сериализовать / десериализовать контекст сопрограммы. По крайней мере, все, что будет десериализовано, не будет ожидаемой сопрограммой.
2. Вы могли бы написать, например, генератор, который разрешал бы сериализацию и возобновлял генерацию с той же точки в последовательности при десериализации.
3. Согласен. Генератор в этом случае будет типом, поддерживающим сопрограмму (предоставляющим необходимые функции и признаки типа для использования в co_yield / await / return ). Включение сериализации для его состояния определенно имело бы свое применение. ОП спросил о сериализации контекста сопрограммы, что для меня звучало как сериализация состояния сопрограммы, выделенного в куче. В стандарте нет формального определения «контекста сопрограммы», только контекст приостановки, который в основном является телом функции (везде, где может появиться выражение ожидания), поэтому я приравнял их.