func (p *Pool) log(message string) {
	if p.logFunc != nil {
		p.logFunc(message)
	}
}
log sending logging messages back to the client.
package work
import (
	"errors"
	"fmt"
	"sync"
	"sync/atomic"
	"time"
)
const (
	addRoutine = 1
	rmvRoutine = 2
)
var ErrorInvalidMinRoutines = errors.New("Invalid minimum number of routines")
var ErrorInvalidStatTime = errors.New("Invalid duration for stat time")
type Worker interface {
	Work(id int)
}
type Pool struct {
	minRoutines int             
	statTime    time.Duration   
	counter     int             
	tasks       chan Worker     
	control     chan int        
	kill        chan struct{}   
	shutdown    chan struct{}   
	wg          sync.WaitGroup  
	routines    int64           
	active      int64           
	pending     int64           
	logFunc func(message string)  
}
func New(minRoutines int, statTime time.Duration, logFunc func(message string)) (*Pool, error) {
	if minRoutines <= 0 {
		return nil, ErrorInvalidMinRoutines
	}
	if statTime < time.Millisecond {
		return nil, ErrorInvalidStatTime
	}
	p := Pool{
		minRoutines: minRoutines,
		statTime:    statTime,
		tasks:       make(chan Worker),
		control:     make(chan int),
		kill:        make(chan struct{}),
		shutdown:    make(chan struct{}),
		logFunc:     logFunc,
	}
	p.manager()
	p.Add(minRoutines)
	return &p, nil
}
func (p *Pool) Add(routines int) {
	if routines == 0 {
		return
	}
	cmd := addRoutine
	if routines < 0 {
		routines = routines * -1
		cmd = rmvRoutine
	}
	for i := 0; i < routines; i++ {
		p.control <- cmd
	}
}
func (p *Pool) work(id int) {
done:
	for {
		select {
		case t := <-p.tasks:
			atomic.AddInt64(&p.active, 1)
			{
				t.Work(id)
			}
			atomic.AddInt64(&p.active, -1)
		case <-p.kill:
			break done
		}
	}
	atomic.AddInt64(&p.routines, -1)
	p.wg.Done()
	p.log("Worker : Shutting Down")
}
func (p *Pool) Run(work Worker) {
	atomic.AddInt64(&p.pending, 1)
	{
		p.tasks <- work
	}
	atomic.AddInt64(&p.pending, -1)
}
func (p *Pool) Shutdown() {
	close(p.shutdown)
	p.wg.Wait()
}
func (p *Pool) manager() {
	p.wg.Add(1)
	go func() {
		p.log("Work Manager : Started")
		timer := time.NewTimer(p.statTime)
		for {
			select {
			case <-p.shutdown:
				routines := int(atomic.LoadInt64(&p.routines))
				for i := 0; i < routines; i++ {
					p.kill <- struct{}{}
				}
				p.wg.Done()
				return
			case c := <-p.control:
				switch c {
				case addRoutine:
					p.log("Work Manager : Add Routine")
					p.counter++
					p.wg.Add(1)
					atomic.AddInt64(&p.routines, 1)
					go p.work(p.counter)
				case rmvRoutine:
					p.log("Work Manager : Remove Routine")
					routines := int(atomic.LoadInt64(&p.routines))
					if routines <= p.minRoutines {
						p.log("Work Manager : Reached Minimum Can't Remove")
						break
					}
					p.kill <- struct{}{}
				}
			case <-timer.C:
				routines := atomic.LoadInt64(&p.routines)
				pending := atomic.LoadInt64(&p.pending)
				active := atomic.LoadInt64(&p.active)
				p.log(fmt.Sprintf("Work Manager : Stats : G[%d] P[%d] A[%d]", routines, pending, active))
				timer.Reset(p.statTime)
			}
		}
	}()
}