Oliver Kowalke
the scheduler with its idle() function would introduce extra context switches because idle() enqueues the scheduler to the ready_next-queue before it switches to the next fiber. seams that the scheduler (fiber) is resumed after each (worker)-fiber. boost.fiber tries to prevent this - it switches only between (worker)-fibers, the scheduler functions only like a store for the next fiebrs.
The idea is that yield and friends would switch to the idle fiber only when they reach the end of the ready queue. To be clear: there are two ready queues: ready and next_ready. Yield pops from ready and pushes into next_ready. ready is never empty, as the last element in the list is always the idle fiber. When the idle fiber is run, it moves the content of next_ready into ready and pushes itself at the end of ready. So yes, if you have N ready tasks yielding, there are N+1 context switches (but not 2*N) per iteration. The cost of the additional idle task is amortized over N tasks. On the other hand, yield becomes simply a push+pop+switch. All corner cases (empty queue, handle off thread signals, pump the timer queue) are handled inside the idle task. Of course a completely equivalent setup is to have an idle function and call it at the end of the ready queue. I do not claim that the idle fiber solution is superior; although it find it elegant, it was not really the core of my criticism of the current scheduler. -- gpd