1 // { dg-do run } 2 3 // test boolean return from await_suspend (). 4 5 #include "../coro.h" 6 7 int coro1_dtor_ran = 0; 8 int promise_dtor_ran = 0; 9 10 struct coro1 { 11 struct promise_type; 12 using handle_type = coro::coroutine_handle<coro1::promise_type>; 13 handle_type handle; coro1coro114 coro1 () : handle(0) {} coro1coro115 coro1 (handle_type _handle) 16 : handle(_handle) { 17 PRINT("Created coro1 object from handle"); 18 } 19 coro1 (const coro1 &) = delete; // no copying coro1coro120 coro1 (coro1 &&s) : handle(s.handle) { 21 s.handle = nullptr; 22 PRINT("coro1 mv ctor "); 23 } 24 coro1 &operator = (coro1 &&s) { 25 handle = s.handle; 26 s.handle = nullptr; 27 PRINT("coro1 op= "); 28 return *this; 29 } 30 ~coro1coro131 ~coro1() { 32 PRINT("Destroyed coro1"); 33 coro1_dtor_ran++; 34 // The coro handle will point to an invalid frame by this stage, 35 // the coroutine will already have self-destroyed the frame and 36 // promise. 37 } 38 39 struct suspend_never_prt { await_readycoro1::suspend_never_prt40 bool await_ready() const noexcept { return true; } await_suspendcoro1::suspend_never_prt41 bool await_suspend(handle_type) const noexcept { 42 PRINT ("susp-never-susp"); // never executed. 43 return true; // ... 44 } await_resumecoro1::suspend_never_prt45 void await_resume() const noexcept {PRINT ("susp-never-resume");} ~suspend_never_prtcoro1::suspend_never_prt46 ~suspend_never_prt() {}; 47 }; 48 49 struct suspend_always_prt { await_readycoro1::suspend_always_prt50 bool await_ready() const noexcept { return false; } await_suspendcoro1::suspend_always_prt51 bool await_suspend(handle_type) const noexcept { 52 PRINT ("susp-always-susp, but we're going to continue.. "); 53 return false; // not going to suspend. 54 } await_resumecoro1::suspend_always_prt55 void await_resume() const noexcept { PRINT ("susp-always-resume");} 56 }; 57 58 struct promise_type { promise_typecoro1::promise_type59 promise_type() { PRINT ("Created Promise"); } ~promise_typecoro1::promise_type60 ~promise_type() { 61 PRINT ("Destroyed Promise"); 62 promise_dtor_ran++; 63 } 64 get_return_objectcoro1::promise_type65 coro1 get_return_object () { 66 PRINT ("get_return_object: from handle from promise"); 67 return coro1 (handle_type::from_promise (*this)); 68 } initial_suspendcoro1::promise_type69 auto initial_suspend () { 70 PRINT ("get initial_suspend (always, but really never) "); 71 return suspend_always_prt{}; 72 } final_suspendcoro1::promise_type73 auto final_suspend () noexcept { 74 PRINT ("get final_suspend (always, but never) "); 75 return suspend_always_prt{}; 76 } return_voidcoro1::promise_type77 void return_void () { 78 PRINT ("return_void ()"); 79 } unhandled_exceptioncoro1::promise_type80 void unhandled_exception() { PRINT ("** unhandled exception"); } 81 }; 82 }; 83 84 struct coro1 my_coro()85my_coro () noexcept 86 { 87 PRINT ("coro1: about to return"); 88 co_return; 89 } 90 main()91int main () 92 { 93 { // scope so that we can examine the coro dtor marker. 94 PRINT ("main: creating coro"); 95 96 // This should just run through to completion/destruction. 97 // In both the initial and final await expressions, the await_suspend() 98 // method will return 'false' and prevent the suspension. 99 struct coro1 x = my_coro (); 100 101 PRINT ("main: the coro frame should be already destroyed"); 102 // We will take the running of the promise DTOR as evidence that the 103 // frame was destroyed as expected. 104 if (promise_dtor_ran != 1) 105 { 106 PRINT ("main: apparently we didn't destroy the frame"); 107 abort (); 108 } 109 } 110 if (coro1_dtor_ran != 1 || promise_dtor_ran != 1) 111 { 112 PRINT ("main: bad DTOR counts"); 113 abort (); 114 } 115 PRINT ("main: returning"); 116 return 0; 117 } 118