| 184 | /// @endcode |
| 185 | template<typename T> |
| 186 | PromiseResult<T> await_top_level(Promise<T> p) { |
| 187 | // Handle invalid promises |
| 188 | if (!p.valid()) { |
| 189 | return PromiseResult<T>(Error("Invalid promise")); |
| 190 | } |
| 191 | |
| 192 | // If already completed, return immediately |
| 193 | if (p.is_completed()) { |
| 194 | if (p.is_resolved()) { |
| 195 | return PromiseResult<T>(p.value()); |
| 196 | } else { |
| 197 | return PromiseResult<T>(p.error()); |
| 198 | } |
| 199 | } |
| 200 | |
| 201 | // Track recursion depth to prevent infinite loops |
| 202 | int& await_depth = detail::await_depth_tls(); |
| 203 | if (await_depth > 10) { |
| 204 | return PromiseResult<T>(Error("await_top_level recursion limit exceeded - possible infinite loop")); |
| 205 | } |
| 206 | |
| 207 | ++await_depth; |
| 208 | |
| 209 | // Wait for promise to complete while pumping async tasks |
| 210 | int pump_count = 0; |
| 211 | const int max_pump_iterations = 10000; // Safety limit |
| 212 | |
| 213 | while (!p.is_completed() && pump_count < max_pump_iterations) { |
| 214 | // Update the promise first (in case it's not managed by async system) |
| 215 | p.update(); |
| 216 | |
| 217 | // Check if completed after update |
| 218 | if (p.is_completed()) { |
| 219 | break; |
| 220 | } |
| 221 | |
| 222 | // Platform-agnostic async pump and yield |
| 223 | run(1000); |
| 224 | |
| 225 | ++pump_count; |
| 226 | } |
| 227 | |
| 228 | --await_depth; |
| 229 | |
| 230 | // Check for timeout |
| 231 | if (pump_count >= max_pump_iterations) { |
| 232 | return PromiseResult<T>(Error("await_top_level timeout - promise did not complete")); |
| 233 | } |
| 234 | |
| 235 | // Return the result |
| 236 | if (p.is_resolved()) { |
| 237 | return PromiseResult<T>(p.value()); |
| 238 | } else { |
| 239 | return PromiseResult<T>(p.error()); |
| 240 | } |
| 241 | } |
| 242 | |
| 243 | } // namespace task |