1 /* Include <coroutine> or the equivalent. */ 2 #include "coro.h" 3 4 /* Allow for stand-alone testing with no headers installed. */ 5 #if __has_include(<new>) 6 # include <new> 7 #else 8 9 /* Required when get_return_object_on_allocation_failure() is defined by 10 the promise. We need a no-throw new, and new etc. build the relevant 11 pieces here to avoid needing the headers in the test. */ 12 13 namespace std { 14 struct nothrow_t {}; 15 constexpr nothrow_t nothrow = {}; 16 typedef __SIZE_TYPE__ size_t; 17 } // end namespace std 18 19 void* operator new(std::size_t, const std::nothrow_t&) noexcept; 20 void operator delete(void* __p, const std::nothrow_t&) noexcept; 21 22 #endif 23 24 /* Flags and counters so that we can test that the methods we expected 25 to be called, were called (and the correct number of times). */ 26 27 #ifdef USE_FAILING_OP_NEW 28 extern int used_failing_new; 29 #endif 30 31 #if defined (PROVIDE_NEW_SZT) || defined (PROVIDE_NEW_SZT_INT) 32 extern int used_ovl_new; 33 #endif 34 35 #ifdef PROVIDE_NEW_SZT_NT 36 extern void *malloc (size_t); 37 extern int used_ovl_new_nt; 38 #endif 39 40 #ifdef PROVIDE_DEL_VP 41 extern int used_ovl_del; 42 #endif 43 44 #ifdef PROVIDE_DEL_VP_SZT 45 extern int used_ovl_del_2arg; 46 #endif 47 48 #ifdef PROVIDE_GROOAF 49 extern int used_grooaf; 50 #endif 51 52 struct coro1 { 53 struct promise_type; 54 using handle_type = coro::coroutine_handle<coro1::promise_type>; 55 handle_type handle; coro1coro156 coro1 () noexcept : handle(0) {} coro1coro157 coro1 (handle_type _handle) noexcept 58 : handle(_handle) { 59 PRINT("Created coro1 object from handle"); 60 } 61 coro1 (const coro1 &) = delete; // no copying coro1coro162 coro1 (coro1 &&s) noexcept : handle(s.handle) { 63 s.handle = nullptr; 64 PRINT("coro1 mv ctor "); 65 } 66 coro1 &operator = (coro1 &&s) noexcept { 67 handle = s.handle; 68 s.handle = nullptr; 69 PRINT("coro1 op= "); 70 return *this; 71 } ~coro1coro172 ~coro1() noexcept { 73 PRINT("Destroyed coro1"); 74 if ( handle ) 75 handle.destroy(); 76 } 77 78 struct suspend_never_prt { await_readycoro1::suspend_never_prt79 bool await_ready() const noexcept { return true; } await_suspendcoro1::suspend_never_prt80 void await_suspend(handle_type) const noexcept { PRINT ("susp-never-susp");} await_resumecoro1::suspend_never_prt81 void await_resume() const noexcept { PRINT ("susp-never-resume");} ~suspend_never_prtcoro1::suspend_never_prt82 ~suspend_never_prt() {}; 83 }; 84 85 struct suspend_always_prt { await_readycoro1::suspend_always_prt86 bool await_ready() const noexcept { return false; } await_suspendcoro1::suspend_always_prt87 void await_suspend(handle_type) const noexcept { PRINT ("susp-always-susp");} await_resumecoro1::suspend_always_prt88 void await_resume() const noexcept { PRINT ("susp-always-resume");} 89 }; 90 91 struct promise_type { promise_typecoro1::promise_type92 promise_type() { PRINT ("Created Promise"); } ~promise_typecoro1::promise_type93 ~promise_type() { PRINT ("Destroyed Promise"); } 94 get_return_objectcoro1::promise_type95 auto get_return_object () { 96 PRINT ("get_return_object: handle from promise"); 97 return handle_type::from_promise (*this); 98 } initial_suspendcoro1::promise_type99 auto initial_suspend () { 100 PRINT ("get initial_suspend (always)"); 101 return suspend_always_prt{}; 102 } final_suspendcoro1::promise_type103 auto final_suspend () noexcept { 104 PRINT ("get final_suspend (always)"); 105 return suspend_always_prt{}; 106 } return_voidcoro1::promise_type107 void return_void () { 108 PRINT ("return_void ()"); 109 } unhandled_exceptioncoro1::promise_type110 void unhandled_exception() { PRINT ("** unhandled exception"); } 111 112 #ifdef USE_FAILING_OP_NEW 113 /* Provide an operator, that always fails. */ newcoro1::promise_type114 void *operator new (std::size_t sz) noexcept { 115 PRINT ("promise_type: used failing op new"); 116 used_failing_new++; 117 return nullptr; 118 } 119 #endif 120 121 #ifdef PROVIDE_NEW_SZT newcoro1::promise_type122 void *operator new (std::size_t sz) { 123 PRINT ("promise_type: used overloaded operator new"); 124 used_ovl_new++; 125 return ::operator new(sz); 126 } 127 #endif 128 129 #ifdef PROVIDE_NEW_SZT_NT newcoro1::promise_type130 void *operator new (std::size_t sz, const std::nothrow_t&) noexcept { 131 PRINT ("promise_type: used overloaded operator new NT"); 132 return malloc (sz); 133 } 134 #endif 135 136 #ifdef PROVIDE_NEW_SZT_INT newcoro1::promise_type137 void *operator new (std::size_t sz, int x) { 138 PRINT ("promise_type: used overloaded operator new with int arg"); 139 used_ovl_new += x; 140 return ::operator new(sz); 141 } 142 #endif 143 144 #ifdef PROVIDE_DEL_VP deletecoro1::promise_type145 void operator delete (void *p) { 146 PRINT ("promise_type: used overloaded operator delete 1 arg"); 147 used_ovl_del++; 148 return ::operator delete(p); 149 } 150 #endif 151 152 #ifdef PROVIDE_DEL_VP_SZT deletecoro1::promise_type153 void operator delete (void *p, std::size_t sz) { 154 PRINT ("promise_type: used overloaded operator delete 2 args"); 155 used_ovl_del_2arg++; 156 return ::operator delete(p); 157 } 158 #endif 159 160 #ifdef BOGUS_OPNEW_CASE1 161 /* Provide an operator, but it doesn't match on overload. */ newcoro1::promise_type162 void *operator new (std::size_t sz, char *f) noexcept { 163 PRINT ("promise_type: used bogus op new"); 164 return nullptr; 165 } 166 #endif 167 168 #ifdef BOGUS_OPDEL_CASE1 169 /* Provide an operator, but it doesn't match on overload. */ deletecoro1::promise_type170 void operator delete (void *p, char *f) { 171 PRINT ("promise_type: used bogus overloaded operator delete"); 172 } 173 #endif 174 175 #ifndef BAD_GROOAF_STATIC 176 # define BAD_GROOAF_STATIC static 177 #endif 178 #ifdef PROVIDE_GROOAF get_return_object_on_allocation_failurecoro1::promise_type179 BAD_GROOAF_STATIC coro1 get_return_object_on_allocation_failure () noexcept { 180 PRINT ("alloc fail return"); 181 used_grooaf++; 182 return coro1 (nullptr); 183 } 184 #endif 185 186 }; // promise 187 }; // coro1 188