package main

import (
	"./log"
	"time"

	"go.uber.org/zap"
)

type workPool struct {
	goChan chan chan func(*time.Timer)
	size   int	// goChan 缓冲长度
}

func newWorkPool(size int) *workPool {
	return &workPool{
		goChan: make(chan chan func(*time.Timer), size),
		size:   size,
	}
}

// 加入一个任务
func (wp *workPool) put(f func(*time.Timer)) {
	for len(wp.goChan) > 0 {
		goRun := <-wp.goChan		// 从 channel 读一条chan
		if goRun == nil {
			continue
		}
		select {
		case <-goRun:	// 清空？
		default:
			goRun <- f	//写入, 在 do 中执行
			return
		}
	}
	// when len(wp.goChan) <= 0
	goRun := make(chan func(*time.Timer), 1)	// 当场创建并执行
	goRun <- f
	go wp.do(goRun)
}

// in goroutine
func (wp *workPool) do(one chan func(*time.Timer)) {
	defer func() {
		if e := recover(); e != nil {
			log.Error("recover panic", zap.Any("error", e))
		}
	}()
	timer := time.NewTimer(time.Second * 10)
	defer timer.Stop()
	for {	// 带超时的循环读取
		select {
		case <-timer.C:	// 10s 超时
			close(one)
			f, ok := <-one
			if !ok {
				return	// 关闭成功返回
			}
			f(timer)
			return
		case f, ok := <-one:	//大多数走这里
			if !ok {
				return	// one 可能关闭
			}
			f(timer)
			timer.Reset(time.Second * 10)	// 一次循环重置
		}
		if len(wp.goChan) < wp.size {
			wp.goChan <- one	// 成功执行后入队
		}
	}
}
