Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce get_return_object_on_allocation_failure to Lazy #338

Merged
merged 1 commit into from
Jul 26, 2023

Conversation

ChuanqiXu9
Copy link
Collaborator

This patch tries to introduce get_return_object_on_allocation_failure() to the promise_type of Lazy.

Why do we want to introduce get_return_object_on_allocation_failure()? Since
a coroutine will be roughly converted to:

void *frame_addr = ::operator new(required size);
__promise_ = new (frame_addr) __promise_type(...);
__return_object_ = __promise_.get_return_object();
co_await __promise_.initial_suspend();
try {
    function-body
} catch (...) {
    __promise_.unhandled_exception();
}
co_await __promise_.final_suspend();

Then we can find that the coroutine should be nounwind (noexcept) naturally if
the constructor of the promise_type, the get_return_object() function, the
initial_suspend, the unhandled_exception(), the final_suspend and the allocation
function is noexcept.

For the specific coroutine type, Lazy, all the above except the allocation function
is noexcept. So that we can make every Lazy function noexcept naturally if we make
the allocation function nothrow. This is the reason why we want to introduce
get_return_object_on_allocation_failure() to Lazy.

Note that the optimization may not work in some platforms due the ABI limitations.
Since they need to consider the case that the destructor of an exception can throw
exceptions.

This patch tries to introduce `get_return_object_on_allocation_failure()` to
the promise_type of Lazy.

Why do we want to introduce `get_return_object_on_allocation_failure()`?
Since
a coroutine will be roughly converted to:

```C++
void *frame_addr = ::operator new(required size);
__promise_ = new (frame_addr) __promise_type(...);
__return_object_ = __promise_.get_return_object();
co_await __promise_.initial_suspend();
try {
    function-body
} catch (...) {
    __promise_.unhandled_exception();
}
co_await __promise_.final_suspend();
```

Then we can find that the coroutine should be nounwind (noexcept)
naturally if
the constructor of the promise_type, the get_return_object() function,
the
initial_suspend, the unhandled_exception(), the final_suspend and the
allocation
function is noexcept.

For the specific coroutine type, Lazy, all the above except the
allocation function
is noexcept. So that we can make every Lazy function noexcept naturally
if we make
the allocation function nothrow. This is the reason why we want to
introduce
`get_return_object_on_allocation_failure()` to Lazy.

Note that the optimization may not work in some platforms due the ABI
limitations.
Since they need to consider the case that the destructor of an exception
can throw
exceptions.
@ChuanqiXu9 ChuanqiXu9 merged commit 1661fe5 into alibaba:main Jul 26, 2023
13 checks passed
void (*__resume_)(__allocation_failed_coroutine_frame_ty*) =
__resume_func;
void (*__destroy_)(void*) = __dummy_destroy_func;
class LazyPromise<T> __promise_;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里的exception什么时候被用户touch到

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

当该协程被 resume 时,在 await_resume 中会抛出异常

};

static inline __allocation_failed_coroutine_frame_ty
__allocation_failed_coroutine_frame;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

多个线程同时出现了bad alloc,是否会有race

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmmm 好像是不太对,这种情况因为平时不会耗尽内存所以没遇到,我先 revert 吧

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

其实这里有点尴尬,bad alloc时一般都是内存比较紧张了。只好提前分配比较合理,thread local是不是可以解,没特别想清楚

ChuanqiXu9 added a commit to ChuanqiXu9/async_simple that referenced this pull request Jul 28, 2023
This patch tries to introduce `get_return_object_on_allocation_failure()` to
the promise_type of Lazy.

Why do we want to introduce `get_return_object_on_allocation_failure()`?
Since
a coroutine will be roughly converted to:

```C++
void *frame_addr = ::operator new(required size);
__promise_ = new (frame_addr) __promise_type(...);
__return_object_ = __promise_.get_return_object();
co_await __promise_.initial_suspend();
try {
    function-body
} catch (...) {
    __promise_.unhandled_exception();
}
co_await __promise_.final_suspend();
```

Then we can find that the coroutine should be nounwind (noexcept)
naturally if
the constructor of the promise_type, the get_return_object() function,
the
initial_suspend, the unhandled_exception(), the final_suspend and the
allocation
function is noexcept.

For the specific coroutine type, Lazy, all the above except the
allocation function
is noexcept. So that we can make every Lazy function noexcept naturally
if we make
the allocation function nothrow. This is the reason why we want to
introduce
`get_return_object_on_allocation_failure()` to Lazy.

Note that the optimization may not work in some platforms due the ABI
limitations.
Since they need to consider the case that the destructor of an exception
can throw
exceptions.
RainMark pushed a commit that referenced this pull request Jul 28, 2023
This patch tries to introduce `get_return_object_on_allocation_failure()` to
the promise_type of Lazy.

Why do we want to introduce `get_return_object_on_allocation_failure()`?
Since
a coroutine will be roughly converted to:

```C++
void *frame_addr = ::operator new(required size);
__promise_ = new (frame_addr) __promise_type(...);
__return_object_ = __promise_.get_return_object();
co_await __promise_.initial_suspend();
try {
    function-body
} catch (...) {
    __promise_.unhandled_exception();
}
co_await __promise_.final_suspend();
```

Then we can find that the coroutine should be nounwind (noexcept)
naturally if
the constructor of the promise_type, the get_return_object() function,
the
initial_suspend, the unhandled_exception(), the final_suspend and the
allocation
function is noexcept.

For the specific coroutine type, Lazy, all the above except the
allocation function
is noexcept. So that we can make every Lazy function noexcept naturally
if we make
the allocation function nothrow. This is the reason why we want to
introduce
`get_return_object_on_allocation_failure()` to Lazy.

Note that the optimization may not work in some platforms due the ABI
limitations.
Since they need to consider the case that the destructor of an exception
can throw
exceptions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants