Thread body. Each non-runner context owns one of these. Park until first signal, then run the entry trampoline. The trampoline itself never returns (CoroutineContext::entry_trampoline busy-loops if it falls through), so the *only* way this function returns is via the initial-wait exit branch below. Mid-coroutine teardown is handled by contextSwitch() calling pthread_exit() — the thread terminates
| 110 | /// contextSwitch() calling pthread_exit() — the thread terminates without |
| 111 | /// returning here. |
| 112 | inline void pthread_coro_thread_main(PthreadCoroCtx* self) FL_NOEXCEPT { |
| 113 | { |
| 114 | fl::unique_lock<fl::mutex> lk(self->mutex); |
| 115 | self->cv.wait(lk, [self] { return self->signaled; }); |
| 116 | self->signaled = false; |
| 117 | if (self->exit_requested) { |
| 118 | // Initial-wait exit — destroyContext() called before the |
| 119 | // coroutine ever ran. Drop the lock and exit cleanly so |
| 120 | // destroyContext()'s join() can return. |
| 121 | return; |
| 122 | } |
| 123 | } |
| 124 | |
| 125 | if (self->entry_fn) { |
| 126 | self->entry_fn(); |
| 127 | } |
| 128 | // Unreachable: entry_fn (CoroutineContext::entry_trampoline) busy-loops |
| 129 | // on its own after the final contextSwitch back to the runner. |
| 130 | // Mid-coroutine teardown exits the thread via pthread_exit() inside |
| 131 | // contextSwitch(), so control never returns here from entry_fn(). |
| 132 | } |
| 133 | |
| 134 | class CoroutinePlatformPthread : public ICoroutinePlatform { |
| 135 | public: |