github.com/zhongdalu/gf@v1.0.0/g/os/grpool/grpool.go (about) 1 // Copyright 2017-2019 gf Author(https://github.com/zhongdalu/gf). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/zhongdalu/gf. 6 7 // Package grpool implements a goroutine reusable pool. 8 package grpool 9 10 import ( 11 "errors" 12 13 "github.com/zhongdalu/gf/g/container/glist" 14 "github.com/zhongdalu/gf/g/container/gtype" 15 ) 16 17 // Goroutine Pool 18 type Pool struct { 19 limit int // Max goroutine count limit. 20 count *gtype.Int // Current running goroutine count. 21 list *glist.List // Job list for asynchronous job adding purpose. 22 closed *gtype.Bool // Is pool closed or not. 23 } 24 25 // Default goroutine pool. 26 var pool = New() 27 28 // New creates and returns a new goroutine pool object. 29 // The parameter <limit> is used to limit the max goroutine count, 30 // which is not limited in default. 31 func New(limit ...int) *Pool { 32 p := &Pool{ 33 limit: -1, 34 count: gtype.NewInt(), 35 list: glist.New(), 36 closed: gtype.NewBool(), 37 } 38 if len(limit) > 0 && limit[0] > 0 { 39 p.limit = limit[0] 40 } 41 return p 42 } 43 44 // Add pushes a new job to the pool using default goroutine pool. 45 // The job will be executed asynchronously. 46 func Add(f func()) error { 47 return pool.Add(f) 48 } 49 50 // Size returns current goroutine count of default goroutine pool. 51 func Size() int { 52 return pool.Size() 53 } 54 55 // Jobs returns current job count of default goroutine pool. 56 func Jobs() int { 57 return pool.Jobs() 58 } 59 60 // Add pushes a new job to the pool. 61 // The job will be executed asynchronously. 62 func (p *Pool) Add(f func()) error { 63 for p.closed.Val() { 64 return errors.New("pool closed") 65 } 66 p.list.PushFront(f) 67 var n int 68 for { 69 n = p.count.Val() 70 if p.limit != -1 && n >= p.limit { 71 return nil 72 } 73 if p.count.Cas(n, n+1) { 74 break 75 } 76 } 77 p.fork() 78 return nil 79 } 80 81 // Cap returns the capacity of the pool. 82 // This capacity is defined when pool is created. 83 // If it returns -1 means no limit. 84 func (p *Pool) Cap() int { 85 return p.limit 86 } 87 88 // Size returns current goroutine count of the pool. 89 func (p *Pool) Size() int { 90 return p.count.Val() 91 } 92 93 // Jobs returns current job count of the pool. 94 func (p *Pool) Jobs() int { 95 return p.list.Size() 96 } 97 98 // fork creates a new goroutine pool. 99 func (p *Pool) fork() { 100 go func() { 101 defer p.count.Add(-1) 102 job := (interface{})(nil) 103 for !p.closed.Val() { 104 if job = p.list.PopBack(); job != nil { 105 job.(func())() 106 } else { 107 return 108 } 109 } 110 }() 111 } 112 113 // IsClosed returns if pool is closed. 114 func (p *Pool) IsClosed() bool { 115 return p.closed.Val() 116 } 117 118 // Close closes the goroutine pool, which makes all goroutines exit. 119 func (p *Pool) Close() { 120 p.closed.Set(true) 121 }