1 // { dg-do run } 2 3 // Test returning a T. 4 // We will use the promise to contain this to avoid having to include 5 // additional C++ headers. 6 7 #include "../coro.h" 8 9 struct suspend_never_prt { await_readysuspend_never_prt10 bool await_ready() const noexcept { return true; } await_suspendsuspend_never_prt11 void await_suspend(coro::coroutine_handle<>) const noexcept 12 { PRINT ("susp-never-susp"); } await_resumesuspend_never_prt13 void await_resume() const noexcept { PRINT ("susp-never-resume");} 14 }; 15 16 /* NOTE: this has a DTOR to test that pathway. */ 17 struct suspend_always_prt { await_readysuspend_always_prt18 bool await_ready() const noexcept { return false; } await_suspendsuspend_always_prt19 void await_suspend(coro::coroutine_handle<>) const noexcept 20 { PRINT ("susp-always-susp"); } await_resumesuspend_always_prt21 void await_resume() const noexcept { PRINT ("susp-always-resume"); } ~suspend_always_prtsuspend_always_prt22 ~suspend_always_prt() { PRINT ("susp-always-DTOR"); } 23 }; 24 25 template <typename T> 26 struct coro1 { 27 struct promise_type; 28 using handle_type = coro::coroutine_handle<coro1::promise_type>; 29 handle_type handle; coro1coro130 coro1 () : handle(0) {} coro1coro131 coro1 (handle_type _handle) 32 : handle(_handle) { 33 PRINT("Created coro1 object from handle"); 34 } 35 coro1 (const coro1 &) = delete; // no copying coro1coro136 coro1 (coro1 &&s) : handle(s.handle) { 37 s.handle = nullptr; 38 PRINT("coro1 mv ctor "); 39 } 40 coro1 &operator = (coro1 &&s) { 41 handle = s.handle; 42 s.handle = nullptr; 43 PRINT("coro1 op= "); 44 return *this; 45 } ~coro1coro146 ~coro1() { 47 PRINT("Destroyed coro1"); 48 if ( handle ) 49 handle.destroy(); 50 } 51 52 struct promise_type { 53 T value; promise_typecoro1::promise_type54 promise_type() { PRINT ("Created Promise"); } ~promise_typecoro1::promise_type55 ~promise_type() { PRINT ("Destroyed Promise"); } 56 get_return_objectcoro1::promise_type57 auto get_return_object () { 58 PRINT ("get_return_object: handle from promise"); 59 return handle_type::from_promise (*this); 60 } 61 initial_suspendcoro1::promise_type62 auto initial_suspend () const { 63 PRINT ("get initial_suspend (always)"); 64 return suspend_always_prt{}; 65 } final_suspendcoro1::promise_type66 auto final_suspend () const noexcept { 67 PRINT ("get final_suspend (always)"); 68 return suspend_always_prt{}; 69 } return_valuecoro1::promise_type70 void return_value (T v) { 71 PRINTF ("return_value () %d\n",v); 72 value = v; 73 } get_valuecoro1::promise_type74 T get_value (void) { return value; } unhandled_exceptioncoro1::promise_type75 void unhandled_exception() { PRINT ("** unhandled exception"); } 76 }; 77 }; 78 79 coro1<float> f()80f () noexcept 81 { 82 PRINT ("coro1: about to return"); 83 co_return (float) 42; 84 } 85 main()86int main () 87 { 88 PRINT ("main: create coro1"); 89 coro1<float> x = f (); 90 PRINT ("main: got coro1 - resuming"); 91 if (x.handle.done()) 92 abort(); 93 x.handle.resume(); 94 PRINT ("main: after resume"); 95 int y = x.handle.promise().get_value(); 96 if ( y != (float)42 ) 97 abort (); 98 if (!x.handle.done()) 99 { 100 PRINT ("main: apparently not done..."); 101 abort (); 102 } 103 PRINT ("main: returning"); 104 return 0; 105 } 106