func (p *limitedPool) Close() {
	err := &ErrPoolClosed{s: errClosed}
	p.closeWithError(err)
}
Close cleans up the pool workers and channels and cancels any pending
work still yet to be processed.
call Reset() to reinitialize the pool for use.
package pool
import (
	"fmt"
	"math"
	"runtime"
	"sync"
)
var _ Pool = new(limitedPool)
type limitedPool struct {
	workers uint
	work    chan *workUnit
	cancel  chan struct{}
	closed  bool
	m       sync.RWMutex
}
func NewLimited(workers uint) Pool {
	if workers == 0 {
		panic("invalid workers '0'")
	}
	p := &limitedPool{
		workers: workers,
	}
	p.initialize()
	return p
}
func (p *limitedPool) initialize() {
	p.work = make(chan *workUnit, p.workers*2)
	p.cancel = make(chan struct{})
	p.closed = false
	for i := 0; i < int(p.workers); i++ {
		p.newWorker(p.work, p.cancel)
	}
}
func (p *limitedPool) newWorker(work chan *workUnit, cancel chan struct{}) {
	go func(p *limitedPool) {
		var wu *workUnit
		defer func(p *limitedPool) {
			if err := recover(); err != nil {
				trace := make([]byte, 1<<16)
				n := runtime.Stack(trace, true)
				s := fmt.Sprintf(errRecovery, err, string(trace[:int(math.Min(float64(n), float64(7000)))]))
				iwu := wu
				iwu.err = &ErrRecovery{s: s}
				close(iwu.done)
				p.newWorker(p.work, p.cancel)
			}
		}(p)
		var value interface{}
		var err error
		for {
			select {
			case wu = <-work:
				if wu == nil {
					continue
				}
				if wu.cancelled.Load() == nil {
					value, err = wu.fn(wu)
					wu.writing.Store(struct{}{})
					if wu.cancelled.Load() == nil && wu.cancelling.Load() == nil {
						wu.value, wu.err = value, err
						close(wu.done)
					}
				}
			case <-cancel:
				return
			}
		}
	}(p)
}
func (p *limitedPool) Queue(fn WorkFunc) WorkUnit {
	w := &workUnit{
		done: make(chan struct{}),
		fn:   fn,
	}
	go func() {
		p.m.RLock()
		if p.closed {
			w.err = &ErrPoolClosed{s: errClosed}
			if w.cancelled.Load() == nil {
				close(w.done)
			}
			p.m.RUnlock()
			return
		}
		p.work <- w
		p.m.RUnlock()
	}()
	return w
}
func (p *limitedPool) Reset() {
	p.m.Lock()
	if !p.closed {
		p.m.Unlock()
		return
	}
	p.initialize()
	p.m.Unlock()
}
func (p *limitedPool) closeWithError(err error) {
	p.m.Lock()
	if !p.closed {
		close(p.cancel)
		close(p.work)
		p.closed = true
	}
	for wu := range p.work {
		wu.cancelWithError(err)
	}
	p.m.Unlock()
}
func (p *limitedPool) Cancel() {
	err := &ErrCancelled{s: errCancelled}
	p.closeWithError(err)
}