Francisco J Ballesteroszxfs put fix1449f3310 years agoHistory
100 lines · 2.0 KB · Go
RawDownload
/*	A pool of worker processes. */package work import (	"clive/dbg"	"sync") struct call {	fn    func()	donec chan bool} // A pool of work to do.struct Pool {	calls  chan call	wg     sync.WaitGroup	closed bool} var (	Debug   bool	dprintf = dbg.FlagPrintf(&Debug)) // create a pool of workers with up to n concurrent works.func NewPool(n int) *Pool {	p := &Pool{calls: make(chan call)}	for i := 0; i < n; i++ {		p.wg.Add(1)		go p.worker(i)	}	return p} func (p *Pool) worker(id int) {	defer p.wg.Done()	dprintf("worker#%d started\n", id)	defer dprintf("worker#%d terminated\n", id)	for c := range p.calls {		dprintf("worker#%d fn()...\n", id)		c.fn()		dprintf("worker#%d ...fn()\n", id)		c.donec <- true	}} // Terminate the pool.// Running functions continue to run but no further work is accepted// causing a panic instead.func (p *Pool) Close() {	p.closed = true	close(p.calls)} // Wait until all workers are done, closing if the pool is not yet closed.func (p *Pool) Wait() {	p.Close()	p.wg.Wait()} // Run fn in a worker from the pool.// If there is no worker available, await until there is one// Either way, return a chan that is sent-to when the call completes.// The channel is the one passed or a new one if it is nil.func (p *Pool) Go(donec chan bool, fn func()) chan bool {	if p.closed {		panic("closed pool")	}	dprintf("go call\n")	if donec == nil {		donec = make(chan bool, 1)	}	p.calls <- call{fn: fn, donec: donec}	return donec} // Run fn in a worker from the pool.// If there is no worker available, run the function in the caller process.// Either way, return a chan that is sent-to when the call completes.// The channel is the one passed or a new one if it is nil.func (p *Pool) Call(donec chan bool, fn func()) chan bool {	if p.closed {		panic("closed pool")	}	dprintf("go call\n")	if donec == nil {		donec = make(chan bool, 1)	}	select {	case p.calls <- call{fn: fn, donec: donec}:	default:		fn()		donec <- true	}	return donec}