From d73c3a7453278757121eda42aa0400a156c3f85d Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 20 Aug 2020 13:00:40 -0700 Subject: [PATCH 01/17] Add P0912R5_coroutine. --- tests/std/test.lst | 1 + tests/std/tests/P0912R5_coroutine/env.lst | 4 ++++ 2 files changed, 5 insertions(+) create mode 100644 tests/std/tests/P0912R5_coroutine/env.lst diff --git a/tests/std/test.lst b/tests/std/test.lst index 0e60c21053b..36395d49d18 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -317,6 +317,7 @@ tests\P0896R4_ranges_test_machinery tests\P0896R4_ranges_to_address tests\P0898R3_concepts tests\P0898R3_identity +tests\P0912R5_coroutine tests\P0919R3_heterogeneous_unordered_lookup tests\P0966R1_string_reserve_should_not_shrink tests\P1023R0_constexpr_for_array_comparisons diff --git a/tests/std/tests/P0912R5_coroutine/env.lst b/tests/std/tests/P0912R5_coroutine/env.lst new file mode 100644 index 00000000000..642f530ffad --- /dev/null +++ b/tests/std/tests/P0912R5_coroutine/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_latest_matrix.lst From e72334218706c892417759947a9deb2265f2c71d Mon Sep 17 00:00:00 2001 From: Jonathan Emmett Date: Thu, 20 Aug 2020 13:01:29 -0700 Subject: [PATCH 02/17] Original test case from @joemmett. --- tests/std/tests/P0912R5_coroutine/test.cpp | 90 ++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 tests/std/tests/P0912R5_coroutine/test.cpp diff --git a/tests/std/tests/P0912R5_coroutine/test.cpp b/tests/std/tests/P0912R5_coroutine/test.cpp new file mode 100644 index 00000000000..5d4df78f902 --- /dev/null +++ b/tests/std/tests/P0912R5_coroutine/test.cpp @@ -0,0 +1,90 @@ + +#include +#include + +struct task +{ + struct promise_type + { + int result; + std::coroutine_handle<> prev; + + task get_return_object() + { + return {*this}; + } + + std::suspend_always initial_suspend() { return {}; } + + auto final_suspend() noexcept + { + struct Awaiter + { + bool await_ready() noexcept { return false; } + void await_resume() noexcept {} + std::coroutine_handle<> await_suspend(std::coroutine_handle h) + { + // If there is no previous coroutine to resume we've reached the outermost coroutine. + // Return a noop coroutine to allow control to return back to the caller. + if (!h.promise().prev) + return std::noop_coroutine(); + return h.promise().prev; // resume awaiting coroutine + } + }; + return Awaiter{}; + } + void return_value(const int v) { result = v; } + void unhandled_exception() noexcept { std::terminate(); } + }; + + bool await_ready() const noexcept { return false; } + int await_resume() { return coro.promise().result; } + auto await_suspend(std::coroutine_handle<> enclosing) + { + coro.promise().prev = enclosing; + return coro; // resume ourselves. + } + + task(task&& rhs) noexcept : coro(rhs.coro) { rhs.coro = nullptr; } + task(task const&) = delete; + task(promise_type& p) : coro(std::coroutine_handle::from_promise(p)) {} + + ~task() + { + if (coro) + coro.destroy(); + } + + std::coroutine_handle coro; +}; + +task f(int n) +{ + if (n == 0) + co_return 0; + + co_return 1 + co_await f(n - 1); +} + +int main() +{ + task t = f(10); + std::coroutine_handle<> h = t.coro; + if (h != t.coro) + { + return 1; + } + if (!h || h.done()) + { + return 1; + } + + h(); + + int val = t.coro.promise().result; + + if (val != 10) + { + return 1; + } +} From 3b51dfcaacfbde9243280917af7e448bc5697f8b Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 20 Aug 2020 13:02:43 -0700 Subject: [PATCH 03/17] clang-format. --- tests/std/tests/P0912R5_coroutine/test.cpp | 70 +++++++++++----------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/tests/std/tests/P0912R5_coroutine/test.cpp b/tests/std/tests/P0912R5_coroutine/test.cpp index 5d4df78f902..2a2b63af2ba 100644 --- a/tests/std/tests/P0912R5_coroutine/test.cpp +++ b/tests/std/tests/P0912R5_coroutine/test.cpp @@ -1,29 +1,26 @@ - #include #include -struct task -{ - struct promise_type - { +struct task { + struct promise_type { int result; std::coroutine_handle<> prev; - task get_return_object() - { + task get_return_object() { return {*this}; } - std::suspend_always initial_suspend() { return {}; } + std::suspend_always initial_suspend() { + return {}; + } - auto final_suspend() noexcept - { - struct Awaiter - { - bool await_ready() noexcept { return false; } + auto final_suspend() noexcept { + struct Awaiter { + bool await_ready() noexcept { + return false; + } void await_resume() noexcept {} - std::coroutine_handle<> await_suspend(std::coroutine_handle h) - { + std::coroutine_handle<> await_suspend(std::coroutine_handle h) { // If there is no previous coroutine to resume we've reached the outermost coroutine. // Return a noop coroutine to allow control to return back to the caller. if (!h.promise().prev) @@ -33,24 +30,32 @@ struct task }; return Awaiter{}; } - void return_value(const int v) { result = v; } - void unhandled_exception() noexcept { std::terminate(); } + void return_value(const int v) { + result = v; + } + void unhandled_exception() noexcept { + std::terminate(); + } }; - bool await_ready() const noexcept { return false; } - int await_resume() { return coro.promise().result; } - auto await_suspend(std::coroutine_handle<> enclosing) - { + bool await_ready() const noexcept { + return false; + } + int await_resume() { + return coro.promise().result; + } + auto await_suspend(std::coroutine_handle<> enclosing) { coro.promise().prev = enclosing; return coro; // resume ourselves. } - task(task&& rhs) noexcept : coro(rhs.coro) { rhs.coro = nullptr; } + task(task&& rhs) noexcept : coro(rhs.coro) { + rhs.coro = nullptr; + } task(task const&) = delete; task(promise_type& p) : coro(std::coroutine_handle::from_promise(p)) {} - ~task() - { + ~task() { if (coro) coro.destroy(); } @@ -58,24 +63,20 @@ struct task std::coroutine_handle coro; }; -task f(int n) -{ +task f(int n) { if (n == 0) co_return 0; co_return 1 + co_await f(n - 1); } -int main() -{ - task t = f(10); +int main() { + task t = f(10); std::coroutine_handle<> h = t.coro; - if (h != t.coro) - { + if (h != t.coro) { return 1; } - if (!h || h.done()) - { + if (!h || h.done()) { return 1; } @@ -83,8 +84,7 @@ int main() int val = t.coro.promise().result; - if (val != 10) - { + if (val != 10) { return 1; } } From 13e3d5dac51cda35ed0347ad0975522ba0d3e774 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 20 Aug 2020 13:05:37 -0700 Subject: [PATCH 04/17] Add braces and newlines. --- tests/std/tests/P0912R5_coroutine/test.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/tests/std/tests/P0912R5_coroutine/test.cpp b/tests/std/tests/P0912R5_coroutine/test.cpp index 2a2b63af2ba..b5738e094ce 100644 --- a/tests/std/tests/P0912R5_coroutine/test.cpp +++ b/tests/std/tests/P0912R5_coroutine/test.cpp @@ -19,20 +19,27 @@ struct task { bool await_ready() noexcept { return false; } + void await_resume() noexcept {} + std::coroutine_handle<> await_suspend(std::coroutine_handle h) { // If there is no previous coroutine to resume we've reached the outermost coroutine. // Return a noop coroutine to allow control to return back to the caller. - if (!h.promise().prev) + if (!h.promise().prev) { return std::noop_coroutine(); + } + return h.promise().prev; // resume awaiting coroutine } }; + return Awaiter{}; } + void return_value(const int v) { result = v; } + void unhandled_exception() noexcept { std::terminate(); } @@ -41,9 +48,11 @@ struct task { bool await_ready() const noexcept { return false; } + int await_resume() { return coro.promise().result; } + auto await_suspend(std::coroutine_handle<> enclosing) { coro.promise().prev = enclosing; return coro; // resume ourselves. @@ -52,20 +61,24 @@ struct task { task(task&& rhs) noexcept : coro(rhs.coro) { rhs.coro = nullptr; } + task(task const&) = delete; + task(promise_type& p) : coro(std::coroutine_handle::from_promise(p)) {} ~task() { - if (coro) + if (coro) { coro.destroy(); + } } std::coroutine_handle coro; }; task f(int n) { - if (n == 0) + if (n == 0) { co_return 0; + } co_return 1 + co_await f(n - 1); } @@ -73,9 +86,11 @@ task f(int n) { int main() { task t = f(10); std::coroutine_handle<> h = t.coro; + if (h != t.coro) { return 1; } + if (!h || h.done()) { return 1; } From 73c9189d9d5c6f94ebd35d26a4148555433ec378 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 20 Aug 2020 13:14:36 -0700 Subject: [PATCH 05/17] Rename to Task and Promise, add promise_type typedef. --- tests/std/tests/P0912R5_coroutine/test.cpp | 24 ++++++++++++---------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/tests/std/tests/P0912R5_coroutine/test.cpp b/tests/std/tests/P0912R5_coroutine/test.cpp index b5738e094ce..8e0ff422203 100644 --- a/tests/std/tests/P0912R5_coroutine/test.cpp +++ b/tests/std/tests/P0912R5_coroutine/test.cpp @@ -1,12 +1,12 @@ #include #include -struct task { - struct promise_type { +struct Task { + struct Promise { int result; std::coroutine_handle<> prev; - task get_return_object() { + Task get_return_object() { return {*this}; } @@ -22,7 +22,7 @@ struct task { void await_resume() noexcept {} - std::coroutine_handle<> await_suspend(std::coroutine_handle h) { + std::coroutine_handle<> await_suspend(std::coroutine_handle h) { // If there is no previous coroutine to resume we've reached the outermost coroutine. // Return a noop coroutine to allow control to return back to the caller. if (!h.promise().prev) { @@ -45,6 +45,8 @@ struct task { } }; + using promise_type = Promise; + bool await_ready() const noexcept { return false; } @@ -58,24 +60,24 @@ struct task { return coro; // resume ourselves. } - task(task&& rhs) noexcept : coro(rhs.coro) { + Task(Task&& rhs) noexcept : coro(rhs.coro) { rhs.coro = nullptr; } - task(task const&) = delete; + Task(Task const&) = delete; - task(promise_type& p) : coro(std::coroutine_handle::from_promise(p)) {} + Task(Promise& p) : coro(std::coroutine_handle::from_promise(p)) {} - ~task() { + ~Task() { if (coro) { coro.destroy(); } } - std::coroutine_handle coro; + std::coroutine_handle coro; }; -task f(int n) { +Task f(int n) { if (n == 0) { co_return 0; } @@ -84,7 +86,7 @@ task f(int n) { } int main() { - task t = f(10); + Task t = f(10); std::coroutine_handle<> h = t.coro; if (h != t.coro) { From eb1e67f87ab5026fd20e6ac8f13cb5c8cacaade0 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 20 Aug 2020 13:15:35 -0700 Subject: [PATCH 06/17] Rename prev to previous (avoiding std::prev confusion). --- tests/std/tests/P0912R5_coroutine/test.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/std/tests/P0912R5_coroutine/test.cpp b/tests/std/tests/P0912R5_coroutine/test.cpp index 8e0ff422203..dbbad93fe8b 100644 --- a/tests/std/tests/P0912R5_coroutine/test.cpp +++ b/tests/std/tests/P0912R5_coroutine/test.cpp @@ -4,7 +4,7 @@ struct Task { struct Promise { int result; - std::coroutine_handle<> prev; + std::coroutine_handle<> previous; Task get_return_object() { return {*this}; @@ -25,11 +25,11 @@ struct Task { std::coroutine_handle<> await_suspend(std::coroutine_handle h) { // If there is no previous coroutine to resume we've reached the outermost coroutine. // Return a noop coroutine to allow control to return back to the caller. - if (!h.promise().prev) { + if (!h.promise().previous) { return std::noop_coroutine(); } - return h.promise().prev; // resume awaiting coroutine + return h.promise().previous; // resume awaiting coroutine } }; @@ -56,7 +56,7 @@ struct Task { } auto await_suspend(std::coroutine_handle<> enclosing) { - coro.promise().prev = enclosing; + coro.promise().previous = enclosing; return coro; // resume ourselves. } From ceb06ec8a31b24624b015d98d9b36d2495c323b4 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 20 Aug 2020 13:17:25 -0700 Subject: [PATCH 07/17] using namespace std; --- tests/std/tests/P0912R5_coroutine/test.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/tests/std/tests/P0912R5_coroutine/test.cpp b/tests/std/tests/P0912R5_coroutine/test.cpp index dbbad93fe8b..2277c86bd81 100644 --- a/tests/std/tests/P0912R5_coroutine/test.cpp +++ b/tests/std/tests/P0912R5_coroutine/test.cpp @@ -1,16 +1,17 @@ #include #include +using namespace std; struct Task { struct Promise { int result; - std::coroutine_handle<> previous; + coroutine_handle<> previous; Task get_return_object() { return {*this}; } - std::suspend_always initial_suspend() { + suspend_always initial_suspend() { return {}; } @@ -22,11 +23,11 @@ struct Task { void await_resume() noexcept {} - std::coroutine_handle<> await_suspend(std::coroutine_handle h) { + coroutine_handle<> await_suspend(coroutine_handle h) { // If there is no previous coroutine to resume we've reached the outermost coroutine. // Return a noop coroutine to allow control to return back to the caller. if (!h.promise().previous) { - return std::noop_coroutine(); + return noop_coroutine(); } return h.promise().previous; // resume awaiting coroutine @@ -41,7 +42,7 @@ struct Task { } void unhandled_exception() noexcept { - std::terminate(); + terminate(); } }; @@ -55,7 +56,7 @@ struct Task { return coro.promise().result; } - auto await_suspend(std::coroutine_handle<> enclosing) { + auto await_suspend(coroutine_handle<> enclosing) { coro.promise().previous = enclosing; return coro; // resume ourselves. } @@ -66,7 +67,7 @@ struct Task { Task(Task const&) = delete; - Task(Promise& p) : coro(std::coroutine_handle::from_promise(p)) {} + Task(Promise& p) : coro(coroutine_handle::from_promise(p)) {} ~Task() { if (coro) { @@ -74,7 +75,7 @@ struct Task { } } - std::coroutine_handle coro; + coroutine_handle coro; }; Task f(int n) { @@ -86,8 +87,8 @@ Task f(int n) { } int main() { - Task t = f(10); - std::coroutine_handle<> h = t.coro; + Task t = f(10); + coroutine_handle<> h = t.coro; if (h != t.coro) { return 1; From 27d69778d2f3114a7861b87f7303c038643dac10 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 20 Aug 2020 13:23:48 -0700 Subject: [PATCH 08/17] Use assert. --- tests/std/tests/P0912R5_coroutine/test.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/tests/std/tests/P0912R5_coroutine/test.cpp b/tests/std/tests/P0912R5_coroutine/test.cpp index 2277c86bd81..f48527a69d5 100644 --- a/tests/std/tests/P0912R5_coroutine/test.cpp +++ b/tests/std/tests/P0912R5_coroutine/test.cpp @@ -1,3 +1,4 @@ +#include #include #include using namespace std; @@ -90,19 +91,13 @@ int main() { Task t = f(10); coroutine_handle<> h = t.coro; - if (h != t.coro) { - return 1; - } - - if (!h || h.done()) { - return 1; - } + assert(h == t.coro); + assert(h); + assert(!h.done()); h(); int val = t.coro.promise().result; - if (val != 10) { - return 1; - } + assert(val == 10); } From 853a45831d865a654624bca150b3a2b104682667 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 20 Aug 2020 13:26:50 -0700 Subject: [PATCH 09/17] Task's move ctor already deletes the copy ctor. --- tests/std/tests/P0912R5_coroutine/test.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/std/tests/P0912R5_coroutine/test.cpp b/tests/std/tests/P0912R5_coroutine/test.cpp index f48527a69d5..cfd6c4edcfb 100644 --- a/tests/std/tests/P0912R5_coroutine/test.cpp +++ b/tests/std/tests/P0912R5_coroutine/test.cpp @@ -66,8 +66,6 @@ struct Task { rhs.coro = nullptr; } - Task(Task const&) = delete; - Task(Promise& p) : coro(coroutine_handle::from_promise(p)) {} ~Task() { From 018fd193ce60de14184b8f317c8611a71ecf7a9e Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 20 Aug 2020 13:28:08 -0700 Subject: [PATCH 10/17] Add const. --- tests/std/tests/P0912R5_coroutine/test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/std/tests/P0912R5_coroutine/test.cpp b/tests/std/tests/P0912R5_coroutine/test.cpp index cfd6c4edcfb..bbf02a9625b 100644 --- a/tests/std/tests/P0912R5_coroutine/test.cpp +++ b/tests/std/tests/P0912R5_coroutine/test.cpp @@ -77,7 +77,7 @@ struct Task { coroutine_handle coro; }; -Task f(int n) { +Task f(const int n) { if (n == 0) { co_return 0; } @@ -95,7 +95,7 @@ int main() { h(); - int val = t.coro.promise().result; + const int val = t.coro.promise().result; assert(val == 10); } From 1fe4d47c6798b681a69a4affffc3b60942a117c2 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 20 Aug 2020 13:38:59 -0700 Subject: [PATCH 11/17] Test triangular numbers to do slightly nontrivial work. --- tests/std/tests/P0912R5_coroutine/test.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/std/tests/P0912R5_coroutine/test.cpp b/tests/std/tests/P0912R5_coroutine/test.cpp index bbf02a9625b..2430819f6e4 100644 --- a/tests/std/tests/P0912R5_coroutine/test.cpp +++ b/tests/std/tests/P0912R5_coroutine/test.cpp @@ -77,16 +77,16 @@ struct Task { coroutine_handle coro; }; -Task f(const int n) { +Task triangular_number(const int n) { if (n == 0) { co_return 0; } - co_return 1 + co_await f(n - 1); + co_return n + co_await triangular_number(n - 1); } int main() { - Task t = f(10); + Task t = triangular_number(10); coroutine_handle<> h = t.coro; assert(h == t.coro); @@ -97,5 +97,5 @@ int main() { const int val = t.coro.promise().result; - assert(val == 10); + assert(val == 55); } From 60c7087d4129e4cebec7078d638cd9ef9ebd990f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 20 Aug 2020 13:42:39 -0700 Subject: [PATCH 12/17] Comment punctuation. --- tests/std/tests/P0912R5_coroutine/test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/std/tests/P0912R5_coroutine/test.cpp b/tests/std/tests/P0912R5_coroutine/test.cpp index 2430819f6e4..7f89a75541b 100644 --- a/tests/std/tests/P0912R5_coroutine/test.cpp +++ b/tests/std/tests/P0912R5_coroutine/test.cpp @@ -25,7 +25,7 @@ struct Task { void await_resume() noexcept {} coroutine_handle<> await_suspend(coroutine_handle h) { - // If there is no previous coroutine to resume we've reached the outermost coroutine. + // If there is no previous coroutine to resume, we've reached the outermost coroutine. // Return a noop coroutine to allow control to return back to the caller. if (!h.promise().previous) { return noop_coroutine(); @@ -59,7 +59,7 @@ struct Task { auto await_suspend(coroutine_handle<> enclosing) { coro.promise().previous = enclosing; - return coro; // resume ourselves. + return coro; // resume ourselves } Task(Task&& rhs) noexcept : coro(rhs.coro) { From 174226d8eb79af5389e15d4b430af51d40b2a300 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 20 Aug 2020 13:51:02 -0700 Subject: [PATCH 13/17] Avoid negated test, extract h.promise().previous. --- tests/std/tests/P0912R5_coroutine/test.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/std/tests/P0912R5_coroutine/test.cpp b/tests/std/tests/P0912R5_coroutine/test.cpp index 7f89a75541b..e5de87e427d 100644 --- a/tests/std/tests/P0912R5_coroutine/test.cpp +++ b/tests/std/tests/P0912R5_coroutine/test.cpp @@ -25,13 +25,13 @@ struct Task { void await_resume() noexcept {} coroutine_handle<> await_suspend(coroutine_handle h) { - // If there is no previous coroutine to resume, we've reached the outermost coroutine. - // Return a noop coroutine to allow control to return back to the caller. - if (!h.promise().previous) { - return noop_coroutine(); + if (auto& p = h.promise().previous; p) { + return p; // resume awaiting coroutine } - return h.promise().previous; // resume awaiting coroutine + // If there is no previous coroutine to resume, we've reached the outermost coroutine. + // Return a noop coroutine to allow control to return back to the caller. + return noop_coroutine(); } }; From fd452a0e0233ab129123029ec8fc73a20e225116 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 20 Aug 2020 14:24:27 -0700 Subject: [PATCH 14/17] Init result{-1000}, rename to pre, assert(h.done()). --- tests/std/tests/P0912R5_coroutine/test.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/std/tests/P0912R5_coroutine/test.cpp b/tests/std/tests/P0912R5_coroutine/test.cpp index e5de87e427d..377f21a3112 100644 --- a/tests/std/tests/P0912R5_coroutine/test.cpp +++ b/tests/std/tests/P0912R5_coroutine/test.cpp @@ -5,7 +5,7 @@ using namespace std; struct Task { struct Promise { - int result; + int result{-1000}; coroutine_handle<> previous; Task get_return_object() { @@ -25,8 +25,8 @@ struct Task { void await_resume() noexcept {} coroutine_handle<> await_suspend(coroutine_handle h) { - if (auto& p = h.promise().previous; p) { - return p; // resume awaiting coroutine + if (auto& pre = h.promise().previous; pre) { + return pre; // resume awaiting coroutine } // If there is no previous coroutine to resume, we've reached the outermost coroutine. @@ -95,6 +95,10 @@ int main() { h(); + assert(h == t.coro); + assert(h); + assert(h.done()); + const int val = t.coro.promise().result; assert(val == 55); From e0d577f54904ef01143e81dc3ebf5562b11fc72f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 20 Aug 2020 14:32:35 -0700 Subject: [PATCH 15/17] Track g_tasks_destroyed. --- tests/std/tests/P0912R5_coroutine/test.cpp | 34 +++++++++++++++------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/tests/std/tests/P0912R5_coroutine/test.cpp b/tests/std/tests/P0912R5_coroutine/test.cpp index 377f21a3112..807c2aa1912 100644 --- a/tests/std/tests/P0912R5_coroutine/test.cpp +++ b/tests/std/tests/P0912R5_coroutine/test.cpp @@ -3,6 +3,8 @@ #include using namespace std; +int g_tasks_destroyed{0}; + struct Task { struct Promise { int result{-1000}; @@ -69,6 +71,8 @@ struct Task { Task(Promise& p) : coro(coroutine_handle::from_promise(p)) {} ~Task() { + ++g_tasks_destroyed; + if (coro) { coro.destroy(); } @@ -86,20 +90,28 @@ Task triangular_number(const int n) { } int main() { - Task t = triangular_number(10); - coroutine_handle<> h = t.coro; + assert(g_tasks_destroyed == 0); + + { + Task t = triangular_number(10); + coroutine_handle<> h = t.coro; - assert(h == t.coro); - assert(h); - assert(!h.done()); + assert(h == t.coro); + assert(h); + assert(!h.done()); - h(); + h(); - assert(h == t.coro); - assert(h); - assert(h.done()); + assert(h == t.coro); + assert(h); + assert(h.done()); - const int val = t.coro.promise().result; + assert(g_tasks_destroyed == 10); // triangular_number() called for [0, 9] + + const int val = t.coro.promise().result; + + assert(val == 55); + } - assert(val == 55); + assert(g_tasks_destroyed == 11); // triangular_number() called for [0, 10] } From 5e755c207367538b24d639734a65da27640a3b6b Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 20 Aug 2020 14:46:56 -0700 Subject: [PATCH 16/17] Add banner, guard __cpp_lib_coroutine >= 201902L. --- tests/std/tests/P0912R5_coroutine/test.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/std/tests/P0912R5_coroutine/test.cpp b/tests/std/tests/P0912R5_coroutine/test.cpp index 807c2aa1912..fac889457cd 100644 --- a/tests/std/tests/P0912R5_coroutine/test.cpp +++ b/tests/std/tests/P0912R5_coroutine/test.cpp @@ -1,3 +1,9 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include // TRANSITION, P0912R5 Library Support For Coroutines +#if defined(__cpp_lib_coroutine) && __cpp_lib_coroutine >= 201902L // TRANSITION, P0912R5 Library Support For Coroutines + #include #include #include @@ -115,3 +121,7 @@ int main() { assert(g_tasks_destroyed == 11); // triangular_number() called for [0, 10] } + +#else // ^^^ test ^^^ / vvv don't test vvv +int main() {} +#endif // TRANSITION, P0912R5 Library Support For Coroutines From 7d30fefbf8f5a2221533270a58113bfc49ad2d24 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 21 Aug 2020 14:08:34 -0700 Subject: [PATCH 17/17] Code review feedback. --- tests/std/tests/P0912R5_coroutine/test.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/std/tests/P0912R5_coroutine/test.cpp b/tests/std/tests/P0912R5_coroutine/test.cpp index fac889457cd..8c8baa39bea 100644 --- a/tests/std/tests/P0912R5_coroutine/test.cpp +++ b/tests/std/tests/P0912R5_coroutine/test.cpp @@ -17,7 +17,7 @@ struct Task { coroutine_handle<> previous; Task get_return_object() { - return {*this}; + return Task{*this}; } suspend_always initial_suspend() { @@ -32,7 +32,7 @@ struct Task { void await_resume() noexcept {} - coroutine_handle<> await_suspend(coroutine_handle h) { + coroutine_handle<> await_suspend(coroutine_handle h) noexcept { if (auto& pre = h.promise().previous; pre) { return pre; // resume awaiting coroutine } @@ -74,7 +74,7 @@ struct Task { rhs.coro = nullptr; } - Task(Promise& p) : coro(coroutine_handle::from_promise(p)) {} + explicit Task(Promise& p) : coro(coroutine_handle::from_promise(p)) {} ~Task() { ++g_tasks_destroyed;