gitee.com/sy_183/go-common@v1.0.5-0.20231205030221-958cfe129b47/lifecycle.v2/wait.go (about) 1 package lifecycle 2 3 import ( 4 "errors" 5 "gitee.com/sy_183/go-common/lifecycle.v2/future" 6 "sync" 7 "sync/atomic" 8 ) 9 10 var ErrWaitInterrupted = errors.New("wait interrupted") 11 12 func WaitFn(fn func() error, interrupter chan struct{}) error { 13 waiter := make(chan error, 1) 14 go func() { waiter <- fn() }() 15 select { 16 case err := <-waiter: 17 return err 18 case <-interrupter: 19 return ErrWaitInterrupted 20 } 21 } 22 23 type Waitable interface { 24 Future(FutureType, Future) Future 25 } 26 27 func Wait[W Waitable](typ FutureType, interrupter chan struct{}, waitable W) (err error) { 28 waiter := make(future.ChanFuture[error], 1) 29 if waitable.Future(typ, waiter) == nil { 30 return nil 31 } 32 select { 33 case err = <-waiter: 34 return err 35 case <-interrupter: 36 return ErrWaitInterrupted 37 } 38 } 39 40 func WaitAll[W Waitable](typ FutureType, interrupter chan struct{}, waitable ...W) (err error) { 41 if len(waitable) == 0 { 42 return nil 43 } 44 count := len(waitable) 45 waiter := make(future.ChanFuture[error], count) 46 for _, w := range waitable { 47 if w.Future(typ, waiter) == nil { 48 count-- 49 } 50 } 51 for i := 0; i < count; i++ { 52 select { 53 case err = <-waiter: 54 if err != nil { 55 return err 56 } 57 case <-interrupter: 58 return ErrWaitInterrupted 59 } 60 } 61 return nil 62 } 63 64 func WaitAny[W Waitable](typ FutureType, interrupter chan struct{}, waitable ...W) (err error) { 65 if len(waitable) == 0 { 66 return nil 67 } 68 count := len(waitable) 69 waiter := make(future.ChanFuture[error], len(waitable)) 70 for _, w := range waitable { 71 if w.Future(typ, waiter) == nil { 72 count-- 73 } 74 } 75 if count == 0 { 76 return nil 77 } 78 select { 79 case err = <-waiter: 80 return err 81 case <-interrupter: 82 return ErrWaitInterrupted 83 } 84 } 85 86 type Starter interface { 87 Background() error 88 89 Start() error 90 91 Future(FutureType, Future) Future 92 } 93 94 func Start[S Starter](interrupter chan struct{}, starter S) (err error) { 95 if err = starter.Background(); err != nil { 96 return err 97 } 98 return Wait(FutureTypeStarted, interrupter, starter) 99 } 100 101 func SequenceStarter[S Starter](starters ...S) Starter { 102 return NewWithFunc(func(Lifecycle) error { 103 for _, starter := range starters { 104 if err := starter.Start(); err != nil { 105 return err 106 } 107 } 108 return nil 109 }, nil, nil) 110 } 111 112 func ParallelStarter[S Starter](lifecycles ...S) Starter { 113 return NewWithFunc(func(Lifecycle) error { 114 for _, lifecycle := range lifecycles { 115 if err := lifecycle.Background(); err != nil { 116 return err 117 } 118 } 119 return WaitAll(FutureTypeStarted, nil, lifecycles...) 120 }, nil, nil) 121 } 122 123 func ParallelStart[S Starter](interrupter chan struct{}, starters ...S) (err error) { 124 for _, starter := range starters { 125 if err = starter.Background(); err != nil { 126 return err 127 } 128 } 129 return WaitAll(FutureTypeStarted, interrupter, starters...) 130 } 131 132 func SequenceStart[S Starter](interrupter chan struct{}, starters ...S) (err error) { 133 for _, starter := range starters { 134 if err = Start(interrupter, starter); err != nil { 135 return 136 } 137 } 138 return nil 139 } 140 141 type Closer interface { 142 Close() error 143 144 Future(FutureType, Future) Future 145 } 146 147 func SequenceCloser[C Closer](closers ...C) Closer { 148 closer := NewInterruptedWithFunc(nil, func(_ Lifecycle, interrupter chan struct{}) error { 149 defer SequenceClose(closers...) 150 <-interrupter 151 return nil 152 }) 153 closer.Start() 154 return closer 155 } 156 157 func ParallelCloser[C Closer](closers ...C) Closer { 158 closer := NewInterruptedWithFunc(nil, func(_ Lifecycle, interrupter chan struct{}) error { 159 defer ParallelClose(closers...) 160 <-interrupter 161 return nil 162 }) 163 closer.Start() 164 return closer 165 } 166 167 func SequenceClose[C Closer](closers ...C) { 168 waiter := make(future.ChanFuture[error], 1) 169 for _, closer := range closers { 170 if err := closer.Close(); err == nil { 171 if closer.Future(FutureTypeClosed, waiter) != nil { 172 <-waiter 173 } 174 } 175 } 176 } 177 178 func ParallelClose[C Closer](closers ...C) { 179 var count int 180 waiter := make(future.ChanFuture[error], len(closers)) 181 for _, closer := range closers { 182 if err := closer.Close(); err == nil { 183 if closer.Future(FutureTypeClosed, waiter) != nil { 184 count++ 185 } 186 } 187 } 188 for i := 0; i < count; i++ { 189 <-waiter 190 } 191 } 192 193 type RelationStarter struct { 194 Lifecycle Lifecycle 195 Depends []*RelationStarter 196 Nowait bool 197 before []*RelationStarter 198 199 initializer sync.Once 200 started atomic.Bool 201 ref atomic.Int64 202 waiter *sync.WaitGroup 203 204 err error 205 } 206 207 func NewRelationStarter(lifecycle Lifecycle, nowait bool, depends ...*RelationStarter) *RelationStarter { 208 s := &RelationStarter{ 209 Lifecycle: lifecycle, 210 Depends: depends, 211 Nowait: nowait, 212 } 213 return s 214 } 215 216 func (s *RelationStarter) init() { 217 for _, depend := range s.Depends { 218 depend.before = append(depend.before, s) 219 } 220 if s.waiter == nil { 221 s.waiter = new(sync.WaitGroup) 222 } 223 s.waiter.Add(1) 224 for _, depend := range s.Depends { 225 s.ref.Add(1) 226 depend.waiter = s.waiter 227 depend.initializer.Do(depend.init) 228 } 229 } 230 231 func (s *RelationStarter) startComplete(err error) { 232 defer s.waiter.Done() 233 s.err = err 234 if err != nil { 235 for _, before := range s.before { 236 if before.started.CompareAndSwap(false, true) { 237 before.startComplete(err) 238 } 239 } 240 return 241 } 242 for _, before := range s.before { 243 if before.ref.Add(-1) == 0 { 244 before.background() 245 } 246 } 247 } 248 249 func (s *RelationStarter) background() (err error) { 250 if s.started.CompareAndSwap(false, true) { 251 if s.Lifecycle == nil { 252 s.startComplete(nil) 253 } else { 254 err = s.Lifecycle.Background() 255 if s.Nowait { 256 s.startComplete(nil) 257 } else { 258 if s.Lifecycle.Future(FutureTypeStarted, future.CallbackFuture[error](s.startComplete)) == nil { 259 s.startComplete(nil) 260 } 261 } 262 } 263 } 264 return 265 } 266 267 func (s *RelationStarter) Background() error { 268 s.initializer.Do(s.init) 269 for _, depend := range s.Depends { 270 depend.Background() 271 } 272 if len(s.Depends) == 0 { 273 return s.background() 274 } 275 return nil 276 } 277 278 func (s *RelationStarter) Wait() error { 279 s.initializer.Do(s.init) 280 s.waiter.Wait() 281 return s.err 282 } 283 284 func (s *RelationStarter) Start() error { 285 s.Background() 286 return s.Wait() 287 } 288 289 type RelationCloser struct { 290 Lifecycle Lifecycle 291 Depends []*RelationCloser 292 293 initializer sync.Once 294 ref atomic.Int64 295 waiter *sync.WaitGroup 296 297 err error 298 } 299 300 func NewRelationCloser(lifecycle Lifecycle, depends ...*RelationCloser) *RelationCloser { 301 c := &RelationCloser{ 302 Lifecycle: lifecycle, 303 Depends: depends, 304 } 305 return c 306 } 307 308 func (c *RelationCloser) init() { 309 if c.waiter == nil { 310 c.waiter = new(sync.WaitGroup) 311 } 312 c.waiter.Add(1) 313 for _, depend := range c.Depends { 314 depend.ref.Add(1) 315 depend.waiter = c.waiter 316 depend.initializer.Do(depend.init) 317 } 318 } 319 320 func (c *RelationCloser) closed(err error) { 321 defer c.waiter.Done() 322 c.err = err 323 for _, depend := range c.Depends { 324 if depend.ref.Add(-1) == 0 { 325 depend.Close() 326 } 327 } 328 } 329 330 func (c *RelationCloser) close() (err error) { 331 if c.Lifecycle == nil { 332 c.closed(nil) 333 } else { 334 err = c.Lifecycle.Close() 335 if c.Lifecycle.Future(FutureTypeClosed, future.CallbackFuture[error](c.closed)) == nil { 336 c.closed(nil) 337 } 338 } 339 return 340 } 341 342 func (c *RelationCloser) Close() error { 343 c.initializer.Do(c.init) 344 return c.close() 345 } 346 347 func (c *RelationCloser) Wait() error { 348 c.initializer.Do(c.init) 349 c.waiter.Wait() 350 return c.err 351 } 352 353 func (c *RelationCloser) Shutdown() error { 354 c.Close() 355 return c.Wait() 356 }