github.com/pubgo/xprocess@v0.1.11/xprocess_future/future.promise.go (about) 1 package xprocess_future 2 3 import ( 4 "fmt" 5 "reflect" 6 "sync" 7 8 "github.com/pubgo/xerror" 9 "github.com/pubgo/xlog" 10 "github.com/pubgo/xprocess/xprocess_abc" 11 "github.com/pubgo/xprocess/xprocess_waitgroup" 12 "github.com/pubgo/xprocess/xutil" 13 "go.uber.org/atomic" 14 ) 15 16 type promise struct { 17 stack string 18 closed atomic.Bool 19 done sync.Once 20 err atomic.Error 21 wg xprocess_waitgroup.WaitGroup 22 data chan xprocess_abc.FutureValue 23 } 24 25 func (s *promise) cancel() { s.closed.Store(true) } 26 func (s *promise) waitForClose() { s.done.Do(func() { go func() { s.wg.Wait(); close(s.data) }() }) } 27 func (s *promise) isClosed() bool { return s.closed.Load() } 28 func (s *promise) Await() chan xprocess_abc.FutureValue { 29 s.waitForClose() 30 31 var val = make(chan xprocess_abc.FutureValue) 32 go func() { 33 defer close(val) 34 for data := range s.data { 35 val <- data 36 s.wg.Done() 37 } 38 }() 39 40 return val 41 } 42 43 func (s *promise) yield(data interface{}) { 44 if s.isClosed() { 45 xlog.Warnf("[xprocess] [promise] %s closed", s.stack) 46 return 47 } 48 49 switch val := data.(type) { 50 case func(): 51 s.Go(val) 52 case *futureValue: 53 s.wg.Inc() 54 go func() { s.data <- val }() 55 default: 56 s.wg.Inc() 57 value := newFutureValue() 58 value.values = []reflect.Value{reflect.ValueOf(data)} 59 go func() { s.data <- value }() 60 } 61 } 62 63 func (s *promise) await(val xprocess_abc.FutureValue, fn interface{}) { 64 if s.isClosed() { 65 xlog.Warnf("[xprocess] [promise] %s closed", s.stack) 66 return 67 } 68 69 s.yield(Await(val, fn)) 70 } 71 72 func (s *promise) Map(fn interface{}) (val1 xprocess_abc.Value) { 73 s.waitForClose() 74 75 defer xerror.Resp(func(err xerror.XErr) { val1 = &value{err: err} }) 76 77 xerror.Assert(fn == nil, "[fn] should not be nil") 78 79 var errs []error 80 var values []xprocess_abc.FutureValue 81 for data := range s.Await() { 82 if err := data.Err(); err != nil { 83 errs = append(errs, err) 84 } 85 86 values = append(values, Await(data, fn)) 87 } 88 89 // 遇到未知错误 90 xerror.PanicErrs(errs...) 91 92 if len(values) == 0 { 93 return 94 } 95 96 tfn := reflect.TypeOf(fn) 97 98 // fn没有输出 99 if tfn.NumOut() == 0 { 100 return &value{} 101 } 102 103 var t = tfn.Out(0) 104 var rst = reflect.MakeSlice(reflect.SliceOf(t), 0, len(values)) 105 for i := range values { 106 val := values[i].Raw()[0] 107 108 if !val.IsValid() { 109 if t.Kind() == reflect.Ptr { 110 val = reflect.New(t).Elem() 111 } else { 112 val = reflect.Zero(t) 113 } 114 } 115 116 rst = reflect.Append(rst, val) 117 } 118 xerror.PanicErrs(errs...) 119 120 return &value{val: rst.Interface()} 121 } 122 123 func (s *promise) Go(fn func()) { 124 s.wg.Inc() 125 go func() { 126 defer s.wg.Done() 127 defer xerror.Resp(func(err xerror.XErr) { s.cancel(); s.err.Store(err) }) 128 fn() 129 }() 130 } 131 132 func Promise(fn func(g xprocess_abc.Future)) xprocess_abc.IPromise { 133 xerror.Assert(fn == nil, "[fn] should not be nil") 134 135 s := &promise{data: make(chan xprocess_abc.FutureValue), stack: xutil.FuncStack(fn)} 136 s.Go(func() { fn(&future{p: s}) }) 137 return s 138 } 139 140 func Async(fn interface{}, args ...interface{}) (val1 xprocess_abc.FutureValue) { 141 var value = newFutureValue() 142 143 defer xerror.Resp(func(err xerror.XErr) { val1 = value.setErr(err) }) 144 145 xerror.Assert(fn == nil, "[fn] should not be nil") 146 147 var vfn = xutil.FuncRaw(fn) 148 var data = make(chan []reflect.Value, 1) 149 value.valFn = func() []reflect.Value { return <-data } 150 go func() { 151 defer xerror.Resp(func(err1 xerror.XErr) { 152 value.setErr(err1.WrapF("recovery error, input:%#v, func:%s, caller:%s", 153 args, reflect.TypeOf(fn), xutil.FuncStack(fn))) 154 data <- make([]reflect.Value, 0) 155 }) 156 157 data <- vfn(args...) 158 }() 159 160 return value 161 } 162 163 func Await(val xprocess_abc.FutureValue, fn interface{}) (val1 xprocess_abc.FutureValue) { 164 var value = newFutureValue() 165 166 defer xerror.Resp(func(err xerror.XErr) { val1 = value.setErr(err) }) 167 168 xerror.Assert(val == nil, "[val] should not be nil") 169 xerror.Assert(fn == nil, "[fn] should not be nil") 170 171 var data = make(chan []reflect.Value, 1) 172 value.valFn = func() []reflect.Value { return <-data } 173 174 var vfn = xutil.FuncValue(fn) 175 go func() { 176 if err := val.Err(); err != nil { 177 value.setErr(err) 178 data <- make([]reflect.Value, 0) 179 return 180 } 181 182 defer xerror.Resp(func(err1 xerror.XErr) { 183 value.setErr(err1.WrapF("input:%s, func:%s", val.Raw(), reflect.TypeOf(fn))) 184 data <- make([]reflect.Value, 0) 185 }) 186 187 data <- vfn(val.Raw()...) 188 }() 189 190 return value 191 } 192 193 func valueStr(values ...reflect.Value) string { 194 var data []interface{} 195 for _, dt := range values { 196 var val interface{} 197 if dt.IsValid() { 198 val = dt.Interface() 199 } 200 data = append(data, val) 201 } 202 return fmt.Sprint(data...) 203 } 204 205 func RunComplete(values ...xprocess_abc.FutureValue) (err error) { 206 defer xerror.RespErr(&err) 207 208 var errs []error 209 for i := range values { 210 if err := values[i].Err(); err != nil { 211 errs = append(errs, err) 212 } 213 } 214 215 xerror.PanicErrs(errs...) 216 return nil 217 }