void Dispatcher::contextProcedure(void* ucontext) { assert(firstReusableContext == nullptr); NativeContext context; context.ucontext = ucontext; context.interrupted = false; context.next = nullptr; firstReusableContext = &context; ucontext_t* oldContext = static_cast<ucontext_t*>(context.ucontext); if (swapcontext(oldContext, static_cast<ucontext_t*>(currentContext->ucontext)) == -1) { throw std::runtime_error("Dispatcher::contextProcedure, swapcontext failed, " + lastErrorMessage()); } for (;;) { ++runningContextCount; try { context.procedure(); } catch(std::exception&) { } if (context.group != nullptr) { if (context.groupPrev != nullptr) { assert(context.groupPrev->groupNext == &context); context.groupPrev->groupNext = context.groupNext; if (context.groupNext != nullptr) { assert(context.groupNext->groupPrev == &context); context.groupNext->groupPrev = context.groupPrev; } else { assert(context.group->lastContext == &context); context.group->lastContext = context.groupPrev; } } else { assert(context.group->firstContext == &context); context.group->firstContext = context.groupNext; if (context.groupNext != nullptr) { assert(context.groupNext->groupPrev == &context); context.groupNext->groupPrev = nullptr; } else { assert(context.group->lastContext == &context); if (context.group->firstWaiter != nullptr) { if (firstResumingContext != nullptr) { assert(lastResumingContext->next == nullptr); lastResumingContext->next = context.group->firstWaiter; } else { firstResumingContext = context.group->firstWaiter; } lastResumingContext = context.group->lastWaiter; context.group->firstWaiter = nullptr; } } } pushReusableContext(context); } dispatch(); } };
void Dispatcher::contextProcedure() { assert(GetCurrentThreadId() == threadId); assert(firstReusableContext == nullptr); NativeContext context; context.interrupted = false; context.next = nullptr; context.inExecutionQueue = false; firstReusableContext = &context; SwitchToFiber(currentContext->fiber); for (;;) { ++runningContextCount; try { context.procedure(); } catch (...) { } if (context.group != nullptr) { if (context.groupPrev != nullptr) { assert(context.groupPrev->groupNext == &context); context.groupPrev->groupNext = context.groupNext; if (context.groupNext != nullptr) { assert(context.groupNext->groupPrev == &context); context.groupNext->groupPrev = context.groupPrev; } else { assert(context.group->lastContext == &context); context.group->lastContext = context.groupPrev; } } else { assert(context.group->firstContext == &context); context.group->firstContext = context.groupNext; if (context.groupNext != nullptr) { assert(context.groupNext->groupPrev == &context); context.groupNext->groupPrev = nullptr; } else { assert(context.group->lastContext == &context); if (context.group->firstWaiter != nullptr) { if (firstResumingContext != nullptr) { assert(lastResumingContext->next == nullptr); lastResumingContext->next = context.group->firstWaiter; } else { firstResumingContext = context.group->firstWaiter; } lastResumingContext = context.group->lastWaiter; context.group->firstWaiter = nullptr; } } } pushReusableContext(context); } dispatch(); } }