package grpool import ( "errors" ) // Goroutine Pool type Pool struct { limit int // Max goroutine count limit. count *Int // Current running goroutine count. list *List // Job list for asynchronous job adding purpose. closed *Bool // Is pool closed or not. } // Default goroutine pool. var pool = NewPool() // New creates and returns a new goroutine pool object. // The parameter is used to limit the max goroutine count, // which is not limited in default. func NewPool(limit ...int) *Pool { p := &Pool{ limit: -1, count: NewInt(), list: NewList(true), closed: NewBool(), } if len(limit) > 0 && limit[0] > 0 { p.limit = limit[0] } return p } // Add pushes a new job to the pool using default goroutine pool. // The job will be executed asynchronously. func Add(f func()) error { return pool.Add(f) } // Size returns current goroutine count of default goroutine pool. func Size() int { return pool.Size() } // Jobs returns current job count of default goroutine pool. func Jobs() int { return pool.Jobs() } // Add pushes a new job to the pool. // The job will be executed asynchronously. func (p *Pool) Add(f func()) error { for p.closed.Val() { return errors.New("pool closed") } p.list.PushFront(f) var n int for { n = p.count.Val() if p.limit != -1 && n >= p.limit { return nil } if p.count.Cas(n, n+1) { break } } p.fork() return nil } // Cap returns the capacity of the pool. // This capacity is defined when pool is created. // If it returns -1 means no limit. func (p *Pool) Cap() int { return p.limit } // Size returns current goroutine count of the pool. func (p *Pool) Size() int { return p.count.Val() } // Jobs returns current job count of the pool. func (p *Pool) Jobs() int { return p.list.Size() } // fork creates a new goroutine pool. func (p *Pool) fork() { go func() { defer p.count.Add(-1) job := (interface{})(nil) for !p.closed.Val() { if job = p.list.PopBack(); job != nil { job.(func())() } else { return } } }() } // IsClosed returns if pool is closed. func (p *Pool) IsClosed() bool { return p.closed.Val() } // Close closes the goroutine pool, which makes all goroutines exit. func (p *Pool) Close() { p.closed.Set(true) }