-
-
Notifications
You must be signed in to change notification settings - Fork 240
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #272 from andreasfertig/fixIssue92
Fixed #92: Added support to show coroutines as written.
- Loading branch information
Showing
10 changed files
with
617 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Coroutines {#transformations-coroutines} | ||
|
||
[#92](https://github.com/andreasfertig/cppinsights/issues/92) asked for coroutines support, with the desire to see the | ||
implemented FSM behind them. After investigating this issue for some time the conclusion is to show coroutines as | ||
written. Without support for the implemented FSM behind them. There is a blog post which explains what needs to be done | ||
to show the FSM behind coroutines: [Coroutines in C++ Insights](https://www.andreasfertig.blog/2019/09/coroutines-in-c-insights.html). A | ||
following Twitter poll did not achieve enough confidence (for more information see here: [Coroutines in C++ Insights - The poll result](https://www.andreasfertig.blog/2019/10/coroutines-in-c-insights-the-poll-result.html)), that it is worth at this point to create a questionable implementation. | ||
|
||
One thing to note is, at the moment only libc++ does support coroutines. You will need to enable using libc++ at the web | ||
front end of [C++ Insights](https://cppinsights.io) to get rid of compiler errors. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
// cmdline:-std=c++2a | ||
#include <experimental/coroutine> | ||
|
||
namespace stdx = std::experimental; | ||
|
||
struct generator { | ||
struct promise_type { | ||
int current_value; | ||
stdx::suspend_always yield_value(int value) { | ||
this->current_value = value; | ||
return {}; | ||
} | ||
|
||
stdx::suspend_always initial_suspend() { return {}; } | ||
stdx::suspend_always final_suspend() { return {}; } | ||
generator get_return_object() { return generator{this}; }; | ||
void unhandled_exception() { std::terminate(); } | ||
void return_value(int value) { } | ||
|
||
// gives us getReturnStmtOnAllocFailure | ||
static generator get_return_object_on_allocation_failure(){ | ||
throw std::bad_alloc(); | ||
} | ||
}; | ||
|
||
|
||
// shortening the name | ||
using coro_handle = stdx::coroutine_handle<promise_type>; | ||
|
||
bool await_ready() { return false; } | ||
void await_suspend(coro_handle waiter) { | ||
waiter.resume(); | ||
} | ||
auto await_resume() { | ||
return p.promise().current_value; | ||
} | ||
|
||
generator(generator const&) = delete; | ||
generator(generator &&rhs) : p(rhs.p) { rhs.p = nullptr; } | ||
|
||
~generator() { | ||
if (p) | ||
p.destroy(); | ||
} | ||
|
||
private: | ||
explicit generator(promise_type *p) | ||
: p(coro_handle::from_promise(*p)) {} | ||
|
||
coro_handle p; | ||
}; | ||
|
||
generator simpleReturn(int v ) { | ||
co_return v; | ||
} | ||
|
||
|
||
|
||
generator additionAwaitReturn(int v ) { | ||
// Here we look at an example, where __f->__promise.return_value( contains the two other coroutine expressions with | ||
// a +. Backtracking is required. | ||
// __f->__promise.return_value(__f->__promise_10_24 + __f->__promise_10_51); | ||
co_return co_await simpleReturn(v) + co_await simpleReturn(v) + co_await simpleReturn(v+1); | ||
} | ||
|
||
generator awaitReturn(int v ) { | ||
// Here we look at an example, where __f->__promise.return_value( contains the two other coroutine expressions with | ||
// a +. Backtracking is required. | ||
// __f->__promise.return_value(__f->__promise_10_24 + __f->__promise_10_51); | ||
co_return co_await simpleReturn(v+41); | ||
} | ||
|
||
generator bracedReturn(int v ) { | ||
// Here we look at an example, where __f->__promise.return_value( contains the two other coroutine expressions with | ||
// a +. Backtracking is required. | ||
// __f->__promise.return_value(__f->__promise_10_24 + __f->__promise_10_51); | ||
co_return { v }; | ||
} | ||
|
||
int main() { | ||
auto sr = simpleReturn(3); | ||
|
||
auto aar = additionAwaitReturn(2); | ||
|
||
auto ar = awaitReturn(44); | ||
|
||
auto br = bracedReturn(5); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
// cmdline:-std=c++2a | ||
#include <experimental/coroutine> | ||
|
||
namespace stdx = std::experimental; | ||
|
||
struct generator | ||
{ | ||
struct promise_type | ||
{ | ||
int current_value; | ||
inline stdx::suspend_always yield_value(int value) | ||
{ | ||
this->current_value = value; | ||
return {}; | ||
} | ||
|
||
inline stdx::suspend_always initial_suspend() | ||
{ | ||
return {}; | ||
} | ||
|
||
inline stdx::suspend_always final_suspend() | ||
{ | ||
return {}; | ||
} | ||
|
||
inline generator get_return_object() | ||
{ | ||
return generator{this}; | ||
} | ||
|
||
inline void unhandled_exception() | ||
{ | ||
std::terminate(); | ||
} | ||
|
||
inline void return_value(int value) | ||
{ | ||
} | ||
|
||
static inline generator get_return_object_on_allocation_failure() | ||
{ | ||
throw std::bad_alloc(); | ||
} | ||
|
||
// inline promise_type() noexcept = default; | ||
}; | ||
|
||
using coro_handle = stdx::coroutine_handle<generator::promise_type>; | ||
inline bool await_ready() | ||
{ | ||
return false; | ||
} | ||
|
||
inline void await_suspend(std::experimental::coroutine_handle<generator::promise_type> waiter) | ||
{ | ||
static_cast<std::experimental::coroutine_handle<void>&>(waiter).resume(); | ||
} | ||
|
||
inline int await_resume() | ||
{ | ||
return this->p.promise().current_value; | ||
} | ||
|
||
// inline generator(const generator &) = delete; | ||
inline generator(generator && rhs) | ||
: p{std::experimental::coroutine_handle<generator::promise_type>(rhs.p)} | ||
{ | ||
rhs.p.operator=(nullptr); | ||
} | ||
|
||
inline ~generator() noexcept | ||
{ | ||
if(static_cast<bool>(static_cast<const std::experimental::coroutine_handle<void>&>(this->p).operator bool())) static_cast<std::experimental::coroutine_handle<void>&>(this->p).destroy(); | ||
|
||
|
||
} | ||
|
||
|
||
private: | ||
inline explicit generator(generator::promise_type * p) | ||
: p{std::experimental::coroutine_handle<generator::promise_type>::from_promise(*p)} | ||
{ | ||
} | ||
|
||
std::experimental::coroutine_handle<generator::promise_type> p; | ||
}; | ||
|
||
|
||
|
||
generator simpleReturn(int v) | ||
{ | ||
co_return v; | ||
} | ||
|
||
|
||
|
||
|
||
generator additionAwaitReturn(int v) | ||
{ | ||
co_return (co_await simpleReturn(v) + co_await simpleReturn(v)) + co_await simpleReturn(v + 1); | ||
} | ||
|
||
|
||
generator awaitReturn(int v) | ||
{ | ||
co_return co_await simpleReturn(v + 41); | ||
} | ||
|
||
|
||
generator bracedReturn(int v) | ||
{ | ||
co_return {v}; | ||
} | ||
|
||
|
||
int main() | ||
{ | ||
generator sr = simpleReturn(3); | ||
generator aar = additionAwaitReturn(2); | ||
generator ar = awaitReturn(44); | ||
generator br = bracedReturn(5); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,4 @@ | ||
extern "C" void Foo(); | ||
|
||
|
||
int main() | ||
{ | ||
|
@@ -8,8 +7,5 @@ int main() | |
|
||
|
||
extern "C" { | ||
void Foo() | ||
{ | ||
} | ||
|
||
void Foo() {} | ||
} |
Oops, something went wrong.