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  }