1 // { dg-do run } 2 3 // Check that we correctly operate when the coroutine object is templated. 4 5 #include "../coro.h" 6 7 template <typename T> 8 struct coro1 { 9 struct promise_type; 10 using handle_type = coro::coroutine_handle<coro1::promise_type>; 11 handle_type handle; coro1coro112 coro1 () : handle(0) {} coro1coro113 coro1 (handle_type _handle) 14 : handle(_handle) { 15 PRINT ("Created coro1 object from handle"); 16 } 17 coro1 (const coro1 &) = delete; // no copying coro1coro118 coro1 (coro1 &&s) : handle(s.handle) { 19 s.handle = nullptr; 20 PRINT ("Moved coro1"); 21 } 22 coro1 &operator = (coro1 &&s) { 23 handle = s.handle; 24 s.handle = nullptr; 25 return *this; 26 } ~coro1coro127 ~coro1() { 28 PRINT ("Destroyed coro1"); 29 if ( handle ) 30 handle.destroy(); 31 } 32 33 struct suspend_never_prt { ~suspend_never_prtcoro1::suspend_never_prt34 ~suspend_never_prt() {} await_readycoro1::suspend_never_prt35 bool await_ready() const noexcept { return true; } await_suspendcoro1::suspend_never_prt36 void await_suspend(handle_type h) const noexcept { PRINT ("susp-never-susp");} await_resumecoro1::suspend_never_prt37 void await_resume() const noexcept {PRINT ("susp-never-resume");} 38 }; 39 40 struct suspend_always_prt { 41 T x; await_readycoro1::suspend_always_prt42 bool await_ready() const noexcept { return false; } await_suspendcoro1::suspend_always_prt43 void await_suspend(handle_type) const noexcept { PRINT ("susp-always-susp");} await_resumecoro1::suspend_always_prt44 void await_resume() const noexcept {PRINT ("susp-always-resume");} 45 }; 46 47 /* This returns the int it was constructed with. */ 48 struct suspend_always_intprt { 49 T x; suspend_always_intprtcoro1::suspend_always_intprt50 suspend_always_intprt() : x((T)5) { PRINT ("suspend_always_intprt def ctor"); } suspend_always_intprtcoro1::suspend_always_intprt51 suspend_always_intprt(T _x) : x(_x) 52 { PRINTF ("suspend_always_intprt ctor with %ld\n", (long)x); } ~suspend_always_intprtcoro1::suspend_always_intprt53 ~suspend_always_intprt() {} await_readycoro1::suspend_always_intprt54 bool await_ready() const noexcept { return false; } await_suspendcoro1::suspend_always_intprt55 void await_suspend(coro::coroutine_handle<>) const noexcept { PRINT ("susp-always-susp-int");} await_resumecoro1::suspend_always_intprt56 int await_resume() const noexcept { PRINT ("susp-always-resume-int"); return x;} 57 }; 58 59 struct promise_type { 60 T value; promise_typecoro1::promise_type61 promise_type() { PRINT ("Created Promise"); } ~promise_typecoro1::promise_type62 ~promise_type() { PRINT ("Destroyed Promise"); } 63 get_return_objectcoro1::promise_type64 coro1 get_return_object() { 65 PRINT ("get_return_object: from handle from promise"); 66 return coro1 (handle_type::from_promise (*this)); 67 } 68 initial_suspendcoro1::promise_type69 auto initial_suspend() { 70 PRINT ("get initial_suspend "); 71 return suspend_never_prt{}; 72 } 73 final_suspendcoro1::promise_type74 auto final_suspend() noexcept { 75 PRINT ("get final_suspend"); 76 return suspend_always_prt{}; 77 } 78 return_valuecoro1::promise_type79 void return_value (int v) { 80 PRINTF ("return_value () %ld\n", (long) v); 81 value = v; 82 } 83 await_transformcoro1::promise_type84 auto await_transform (T v) { 85 PRINTF ("await_transform a T () %ld\n", (long)v); 86 return suspend_always_intprt (v); 87 } 88 get_valuecoro1::promise_type89 T get_value () { return value; } unhandled_exceptioncoro1::promise_type90 void unhandled_exception() { PRINT ("** unhandled exception"); } 91 }; 92 }; 93 94 /* Valued with an await_transform. */ 95 int gX = 2; 96 97 template <typename T> f()98coro1<T> f () 99 { 100 for (int i = 0; i < 4; ++i) 101 { 102 gX += co_await 10; 103 } 104 co_return gX; 105 } 106 main()107int main () 108 { 109 PRINT ("main: create coro1"); 110 auto f_coro = f<int>(); 111 112 PRINT ("main: got coro1 - checking gX"); 113 if (gX != 2) 114 { 115 PRINTF ("main: gX is wrong : %d, should be 2\n", gX); 116 abort (); 117 } 118 PRINT ("main: gX OK -- looping"); 119 do { 120 f_coro.handle.resume(); 121 } while (!f_coro.handle.done()); 122 123 int y = f_coro.handle.promise().get_value(); 124 125 if (y != 42) 126 { 127 PRINTF ("main: y is wrong : %d, should be 42\n", y); 128 abort (); 129 } 130 puts ("main: done"); 131 return 0; 132 } 133