🩹 promise_type::operator new — кастомная аллокация фрейма
Корутина выделяет фрейм через ::operator new. Но этот вызов можно перехватить и направить в любой аллокатор — арену, пул, стек. Механизм называется coroutine allocator customization.
👁 Как это работает
Когда компилятор генерирует код запуска корутины, он ищет operator new в двух местах по порядку: сначала в типе promise_type — если есть, использует его; затем глобальный ::operator new.
struct MyPromise {
static void* operator new(std::size_t size) {
return my_pool.allocate(size);
}
static void operator delete(void* ptr, std::size_t size) {
my_pool.deallocate(ptr, size);
}
};
⚡️ Параметры аргументов корутины
Стандарт позволяет передать аргументы самой корутины в operator new. Компилятор сначала пробует сигнатуру с аргументами:
static void* operator new(std::size_t sz, Allocator& alloc, auto&&...) {
return alloc.allocate(sz);
}
Это мощно: можно пробросить аллокатор как первый параметр корутины и использовать его для фрейма — без глобального состояния.
‼️ Heap Elision и operator new
Если компилятор применяет heap elision и вообще убирает аллокацию — ваш кастомный operator new не вызовется. Это нормально. Но если вы используете operator new для отладки размеров, убедитесь что оптимизация отключена (-O0 или [[clang::noinline]] на корутину).
✅ Применение
Кастомный аллокатор в корутинах даёт: lock-free аллокацию, аллокацию с арены (без освобождения по одному), размещение на стеке вызывающего. Последнее — буквально O(1) без heap, если время жизни гарантировано.