Round-robin should stay fair even when tasks have different lifespans. Today a task that finishes early simply drops out of the rotation, and the ones still running close ranks - the trace proves nobody skips a turn and nobody lingers.
Run three tasks of unequal length and assert a finished task leaves the rotation cleanly.
Real programs mix long-lived and short-lived green threads freely, and the scheduler
must not stumble when one finishes ahead of the others. It does not, because Done
just means “do not re-enqueue” - the finished task quietly vanishes and the queue
carries on with whoever is left.
Follow the queue: it starts [1, 2, 3]. Task 1 yields, giving [2, 3, 1]. Task 2
finishes and is dropped, giving [3, 1]. Task 3 yields, giving [1, 3]. Task 1
finishes, giving [3]. Task 3 finishes. The trace is [1, 2, 3, 1, 3] - task 2
appears exactly once, and the survivors keep alternating without missing a beat.
This is the property that lets you spawn and retire green threads at will.
// task 2 is a one-shot; tasks 1 and 3 yield onceoneShot := func() Status { return Done }// reuse twoStep() from the previous lesson for tasks 1 and 3// spawn order: twoStep, oneShot, twoStep