func (f *fifo) Schedule(j Job) {
	f.mu.Lock()
	defer f.mu.Unlock()
	if f.cancel == nil {
		panic("schedule: schedule to stopped scheduler")
	}
	if len(f.pendings) == 0 {
		select {
		case f.resume <- struct{}{}:
		default:
		}
	}
	f.pendings = append(f.pendings, j)
}
Schedule schedules a job that will be ran in FIFO order sequentially.
package schedule
import (
	"sync"
	"golang.org/x/net/context"
)
type Job func(context.Context)
type Scheduler interface {
	Schedule(j Job)
	Pending() int
	Scheduled() int
	Finished() int
	WaitFinish(n int)
	Stop()
}
type fifo struct {
	mu sync.Mutex
	resume    chan struct{}
	scheduled int
	finished  int
	pendings  []Job
	ctx    context.Context
	cancel context.CancelFunc
	finishCond *sync.Cond
	donec      chan struct{}
}
func NewFIFOScheduler() Scheduler {
	f := &fifo{
		resume: make(chan struct{}, 1),
		donec:  make(chan struct{}, 1),
	}
	f.finishCond = sync.NewCond(&f.mu)
	f.ctx, f.cancel = context.WithCancel(context.Background())
	go f.run()
	return f
}