cpp-ru / ideas

Идеи по улучшению языка C++ для обсуждения
https://cpp-ru.github.io/proposals
Creative Commons Zero v1.0 Universal
89 stars 0 forks source link

std::lifetime #517

Open kelbon opened 2 years ago

kelbon commented 2 years ago

В С++ возникла проблема отслеживания лайфтаймов и особенно сильно она проявляется в корутинах, где недостаточно умный компилятор не может оптимизировать аллокацию. Моя идея поможет с этими проблемами и вроде довольно изящно. Суть: Представим, что корутина по ссылке захватила в себя объект из скоупа, где создана, а в конце корутины обращается по этой ссылке и вызывает скажем метод. Если эта ссылка висячая, то это уб, значит этого не может быть, а значит корутина гарантированно переживает переменную по ссылке(если это валидный код). А значит можно не аллоцировать память для этой корутины и сделать её на стеке. Грубо говоря:

// корутина
  task Foo(lifetime_t& life) {
  scope_exit { life.end() };
/// ...
  co_return;
}

void Bar () {
  lifetime_t life;
  Foo(life);
}

Теперь можно добавить к этому немного поддержки стандартной библиотеки

consteval auto std::current_scope() noexcept -> std::lifetime_t;

struct life {
  [[no_unique_address]] std::lifetime_t& lifetime; // некая компиляторная магия позволяющая ссылке тут быть пустой
  ~life() {
    std::die(lifetime);
  }
};

std::current_scope действует по аналогии с std::current_location() только на компиляции. Возвращает уникальное значение типа std:::lifetime_t, которое умеет сравниваться(чтобы быть использованным в качестве шаблонного параметра) Тогда представим реализацию функции-корутины, возвращающей std::generator, который точно знает что всегда может быть на стеке И специальный std::life, который является пустой обёрткой(не занимающей памяти) над std::lifetime_t, которая в деструкторе обращается по ссылке к объекту типа std::lifetime_t

std::generator<int> Foo(std::life = std::current_scope()) {
  co_yield 5;
// в конце вызывается деструктор life, а если корутина
// пережила скоуп, то это уб(обращение по невалидной ссылке), а значит аллоцировать не нужно
  co_return; 
}
apolukhin commented 2 years ago

Хак прикольный, но не даёт 100% гарантии - компилятор может недостаточно хорошо заинлайнить, или тело корутины может оказаться слишком большим, или сама корутина окажется многомегабайтной, или режим оптимизации недостаточно выкручен...

kelbon commented 2 years ago

Хак прикольный, но не даёт 100% гарантии - компилятор может недостаточно хорошо заинлайнить, или тело корутины может оказаться слишком большим, или сама корутина окажется многомегабайтной, или режим оптимизации недостаточно выкручен...

ну если добавлять это в стандарт, то гарантировать оптимизацию по типу возврата из функции

kelbon commented 2 years ago

Хак прикольный

https://github.com/cpp-ru/ideas/issues/514 А вот это не прикольно?()