Комментарии 5
Мне кажется, использование std::shared_ptr здесь лишнее. Вы либо овните корутину в task-е (мануально вызывая .destroy() + suspend_always из final_suspend()) либо "запоминаете все текущие корутины которые активны и которые можно и нужно терминейтить". Это тоже можно сделать пробросив ссылку на что-то что запоминает и регистрируя/удаляя корутину когда случается initial_suspend/final_suspend.
"Овнить" корутину в task - это вариант. Для моего примера он пожалуй даже лучше - проще. Но я использую shared_ptr, чтобы иметь возможность просто запустить корутину как обычную функцию и забыть про нее. Не скажу, что это идеальное решение, так как по сути происходит неявный запуск потока, и я подумываю от такого подхода отказаться в пользу spawn как в boost. Но пока я им пользуюсь.
Второй предложенный вами вариант - откровенно сложнее. И что он дает? Экономит один malloc (и то не всегда, где-то же вы список корутин будете хранить)
возможность просто запустить корутину как обычную функцию и забыть про нее
Хм, как же её тогда терминейтить? Кому-то нужно иметь референс на таск, чтобы вызвать job.terminate(), как у вас в мейне, в примере?
spawn как в boost
это не меняет, наверное, модель того что таска овнит корутину. В случае spawn-а таску (соответственно и корутину) будут овнить внутренности экзекютора в бусте/азио/либо аналог кастомной реализации.
Экономит один malloc (и то не всегда, где-то же вы список корутин будете хранить)
Ну, не совсем. Можно иметь интрузивный список корутин, которые вас интересуют.
откровенно сложнее
но, на практике, имея как идею "останавливать все корутины при каком-то событии", вам нужен список всех таких корутин, чтобы вызвать job.terminate(), не так ли ?
В целом, мне кажется, первый вариант с тем что таска овнит корутину - был бы проще, конкретно для вашего примера в статье. И убрал бы с интернета ещё один пример использования shared_ptr ^_^
Хм, как же её тогда терминейтить?
Никак. Но я ведь не утверждаю, что надо мочь прерывать абсолютно все. Как раз на моей практике это не так. Чаще приходится прерывать "бесконечные" корутины или же awaitable объекты, которые реализованы через корутину, как часть тех же "бесконечных" корутин. А большинства проще и правильнее просто дождаться.
Данная реализация, так сказать, универсальная. Но я согласен, что эффективнее с точки зрения ресурсов и производительности использовать специфичные реализации под разные задачи.
В целом вы правы, но пример я уже не буду исправлять. Иначе наша переписка потеряет смысл :)
Прерывая корутины С++