Как coroutine_handle <Promise>:: from_promise () работает в C ++ - PullRequest
0 голосов
/ 30 октября 2019

I читать , что coroutine_handle можно восстановить из ссылки на объект обещания сопрограммы с использованием функции coroutine_handle<Promise>::from_promise(). Насколько мне известно, объект обещания определяется следующим образом:

class resumable{
public:
  struct promise_type;
  bool resume();
};

struct resumable::promise_type{
  resumable get_return_object() {/**/}
  auto initial_suspend() {/**/}
  auto final_suspend() {/**/}
  void return_void() {}
  void unhandled_exception();
};

Я не могу понять, как может работать реконструкция, учитывая тот факт, что promise_type не содержит никакой ссылки на дескриптор сопрограммы. Напротив, дескриптор сопрограммы хранит ссылку на объект обещания, который может быть возвращен методом promise() дескриптора. Я не могу найти никакой информации о том, что на самом деле происходит в функции from_promise.

1 Ответ

2 голосов
/ 30 октября 2019

Работает по указу. То есть он работает, потому что стандарт говорит , что он работает, и поэтому реализации должны найти способ реализации сопрограмм таким образом, чтобы это было возможно.

При создании сопрограммыРеализация создает две вещи: coroutine_handle и объект обещания. Расположение обеих этих вещей полностью контролируется компилятором. Таким образом, компилятор мог бы очень легко размещать их непрерывно друг с другом, так что стек сопрограммы по сути начинался бы с struct {coroutine_handle<Promise> handle; Promise promise};.

Учитывая эти знания, вы знаете, что дескриптор для любого типа обещания живет sizeof(coroutine_handle<Promise>) байт перед любым promise адресом объекта (требования к выравниванию типа Promise могут отрегулировать это, но такие вещи можно запросить из типа). А поскольку from_promise принимает объект обещания, вы можете просто сместить указатель и привести его к coroutine_handle<Promise>.

Теперь это только один из способов сделать это;реализация не должна делать это таким образом. Важно то, что реализация контролирует, где находится объект обещания относительно внутренних данных сопрограммы. Или, более конкретно, обещание живет внутри этих внутренних данных. Независимо от того, как вы смотрите на это, компилятор знает все, что ему нужно для того, чтобы преобразовать адрес обещания во внутренние данные, необходимые для заполнения coroutine_handle.

...