github.com/chain5j/chain5j-pkg@v1.0.7/pool/groupwork/group.go (about) 1 // Package groupwork 2 // 3 // @author: xwc1125 4 package groupwork 5 6 import ( 7 "context" 8 "errors" 9 "runtime" 10 "sync" 11 12 "github.com/chain5j/chain5j-pkg/pool/pool" 13 "github.com/chain5j/logger" 14 ) 15 16 type Group struct { 17 pool *pool.Pool 18 19 cancel func() 20 21 wg sync.WaitGroup 22 23 errOnce sync.Once 24 err error 25 26 okOnce sync.Once 27 ok interface{} 28 } 29 30 func WithContext(ctx context.Context, poolSize int) (*Group, context.Context) { 31 ctx, cancel := context.WithCancel(ctx) 32 newPool, _ := pool.NewPool(poolSize) 33 return &Group{ 34 cancel: cancel, 35 pool: newPool, 36 }, ctx 37 } 38 39 func (g *Group) WaitErr() error { 40 g.wg.Wait() 41 if g.cancel != nil { 42 g.cancel() 43 } 44 return g.err 45 } 46 func (g *Group) WaitOk() interface{} { 47 g.wg.Wait() 48 if g.cancel != nil { 49 g.cancel() 50 } 51 return g.ok 52 } 53 54 func (g *Group) OnceErr(f func() error) { 55 g.wg.Add(1) 56 g.pool.Submit(func() { 57 defer g.wg.Done() 58 59 if err := f(); err != nil { 60 g.errOnce.Do(func() { 61 g.err = err 62 if g.cancel != nil { 63 g.cancel() 64 } 65 }) 66 } 67 }) 68 } 69 func (g *Group) OnceOk(f func() (interface{}, error)) { 70 g.wg.Add(1) 71 g.pool.Submit(func() { 72 defer g.wg.Done() 73 74 if data, err := f(); err == nil { 75 g.okOnce.Do(func() { 76 g.ok = data 77 if g.cancel != nil { 78 g.cancel() 79 } 80 }) 81 } 82 }) 83 } 84 85 func GoAndWaitErr(handlers ...func() error) (err error) { 86 var wg sync.WaitGroup 87 var once sync.Once 88 for _, f := range handlers { 89 wg.Add(1) 90 go func(handler func() error) { 91 defer func() { 92 if e := recover(); e != nil { 93 buf := make([]byte, 1024) 94 buf = buf[:runtime.Stack(buf, false)] 95 logger.Error("[PANIC]%v\n%s\n", e, buf) 96 once.Do(func() { 97 err = errors.New("panic found in call handlers") 98 }) 99 } 100 wg.Done() 101 }() 102 if e := handler(); e != nil { 103 once.Do(func() { 104 err = e 105 }) 106 } 107 }(f) 108 } 109 wg.Wait() 110 return err 111 } 112 func GoAndWaitOk(handlers ...func() (interface{}, error)) (result interface{}, err error) { 113 var wg sync.WaitGroup 114 var once sync.Once 115 for _, f := range handlers { 116 wg.Add(1) 117 go func(handler func() (interface{}, error)) { 118 defer func() { 119 if e := recover(); e != nil { 120 buf := make([]byte, 1024) 121 buf = buf[:runtime.Stack(buf, false)] 122 logger.Error("[PANIC]%v\n%s\n", e, buf) 123 err = errors.New("panic found in call handlers") 124 } 125 wg.Done() 126 }() 127 if f, e := handler(); e == nil { 128 once.Do(func() { 129 result = f 130 }) 131 } 132 }(f) 133 } 134 wg.Wait() 135 return result, err 136 }