Skip to content

Commit

Permalink
Bring back stopped_exception, it plays nicely now.
Browse files Browse the repository at this point in the history
  • Loading branch information
jnbrq committed Oct 2, 2023
1 parent 9994247 commit 0b93116
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 19 deletions.
31 changes: 31 additions & 0 deletions examples/bug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,40 @@ des::coroutine<> coro2() {
co_await (coro1() || coro1());
}

#if 0

int main() {
des::environment env;
env.bind(coro2());
env.run();
return 0;
}

#endif

#if 1

des::coroutine<> clocks(int i) {
co_await des::timeout(i);
while (true) {
co_await des::timeout(5);
}
}

des::coroutine<> co_main() {
co_await des::async(clocks(1));
co_await clocks(0);
}

int main() {
des::environment env;

env.bind(clocks(0));
env.bind(clocks(1));

// env.bind(co_main());
env.run_for(50);
return 0;
}

#endif
56 changes: 48 additions & 8 deletions examples/exceptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@

using namespace cxxdes::core;

coroutine<> longfn()
{
co_await timeout(100);
co_return;
}

subroutine<> f()
{
throw std::runtime_error("f has thrown an exception!");
Expand All @@ -28,34 +34,67 @@ coroutine<> h()
throw std::runtime_error("h has thrown an exception!");
}

coroutine<> co_main()
coroutine<> co_main1()
{
try
{
co_await h();
}
catch (std::exception &ex)
{
fmt::println("[co_main] Exception: {}", ex.what());
fmt::println("[co_main1] Exception: {}", ex.what());
}

throw std::runtime_error("[co_main] co_main has thrown an exception!");
throw std::runtime_error("[co_main1] co_main has thrown an exception!");
}

coroutine<> co_main2()
{
co_await async(longfn());

try
{
co_await h();
}
catch (std::exception &ex)
{
fmt::println("[co_main2] Exception: {}", ex.what());
}

throw std::runtime_error("[co_main2] co_main has thrown an exception!");
}

void nestedExceptions1()
{
fmt::println("test: nested exceptions 1");

environment env;
env.bind(co_main1());

try
{
env.run();
}
catch (std::exception &ex)
{
fmt::println("[nestedExceptions1] Exception: {}", ex.what());
}
}

void nestedExceptions()
void nestedExceptions2()
{
fmt::println("test: nested exceptions");
fmt::println("test: nested exceptions 2");

environment env;
env.bind(co_main());
env.bind(co_main2());

try
{
env.run();
}
catch (std::exception &ex)
{
fmt::println("[nestedExceptions] Exception: {}", ex.what());
fmt::println("[nestedExceptions2] Exception: {}", ex.what());
}
}

Expand Down Expand Up @@ -144,7 +183,8 @@ void asynchronous2()

int main()
{
nestedExceptions();
nestedExceptions1();
nestedExceptions2();
stopping();
asynchronous1();
asynchronous2();
Expand Down
2 changes: 2 additions & 0 deletions include/cxxdes/core/impl/await_transform.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ struct awaitable_wrapper {
}

auto await_resume() {
if (coro_data_this->stopped())
throw coroutine_data::stopped_exception{};
return a.await_resume();
}
};
Expand Down
17 changes: 13 additions & 4 deletions include/cxxdes/core/impl/coroutine.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -254,11 +254,20 @@ public:
auto final_suspend() noexcept -> std::suspend_never { return {}; }

auto unhandled_exception() -> void {
// update completion tokens with the current exception
coro_data->propagate_exception(std::current_exception());
try {
std::rethrow_exception(std::current_exception());
}
catch (coroutine_data::stopped_exception &) {
// do nothing, we do not need to propagate this exception
// other coroutines will be also stopped by the environment
}
catch (...) {
// update completion tokens with the current exception
coro_data->propagate_exception(std::current_exception());

// schedule the completion tokens
coro_data->do_return();
// schedule the completion tokens
coro_data->do_return();
}
}

template <typename T>
Expand Down
20 changes: 15 additions & 5 deletions include/cxxdes/core/impl/coroutine_data.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,25 @@ struct coroutine_data: memory::reference_counted_base<coroutine_data> {
return env_ != nullptr;
}

void kill() {
while (!call_stack_.empty()) {
call_stack_.back().destroy();
call_stack_.pop_back();
}
void stop() {
stopped_ = true;
}

[[nodiscard]]
bool stopped() {
return stopped_;
}

virtual ~coroutine_data() = default;

protected:
// protected, so cannot be captured by user
struct stopped_exception: std::exception {
const char *what() const noexcept override {
return "stopped";
}
};

template <awaitable A>
friend struct awaitable_wrapper;

Expand Down Expand Up @@ -137,6 +146,7 @@ protected:
time_integral latency_ = 0;
memory::ptr<coroutine_data> parent_;
bool complete_ = false;
bool stopped_ = false;
};


Expand Down
7 changes: 5 additions & 2 deletions include/cxxdes/core/impl/environment.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,10 @@ struct environment {
auto coroutines = std::move(coroutines_);

for (auto coroutine: coroutines) {
coroutine->kill();
if (!coroutine->complete()) {
coroutine->stop();
coroutine->resume();
}
}

while (!tokens_.empty()) {
Expand Down Expand Up @@ -156,7 +159,7 @@ struct environment {
}

~environment() {
// reset();
reset();
}

private:
Expand Down

0 comments on commit 0b93116

Please sign in to comment.