gitee.com/sy_183/go-common@v1.0.5-0.20231205030221-958cfe129b47/lifecycle.v2/lifecycle.go (about)

     1  package lifecycle
     2  
     3  import (
     4  	"gitee.com/sy_183/go-common/lifecycle.v2/future"
     5  	"sync/atomic"
     6  	"unsafe"
     7  )
     8  
     9  type FutureType uint
    10  
    11  const (
    12  	FutureTypeStarted = FutureType(iota)
    13  	FutureTypeClosed  = FutureType(iota)
    14  	futureTypes
    15  )
    16  
    17  type Future future.Future[error]
    18  
    19  type BeforeCallbackType uint
    20  
    21  const (
    22  	BeforeStart = BeforeCallbackType(iota)
    23  	BeforeClose
    24  	beforeCallbackTypes
    25  )
    26  
    27  type AfterCallbackType uint
    28  
    29  const (
    30  	AfterStart = AfterCallbackType(iota)
    31  	AfterClose
    32  	AfterRun
    33  	afterCallbackTypes
    34  )
    35  
    36  type PanicCallbackType uint
    37  
    38  const (
    39  	PanicOnStarting = PanicCallbackType(iota)
    40  	PanicOnRunning
    41  	panicCallbackTypes
    42  )
    43  
    44  type (
    45  	BeforeCallback = func(Lifecycle) error
    46  	AfterCallback  = func(Lifecycle, error)
    47  	PanicCallback  = func(Lifecycle, any) error
    48  )
    49  
    50  type atomicEntry[V any] struct {
    51  	value V
    52  	next  atomic.Pointer[atomicEntry[V]]
    53  }
    54  
    55  type atomicList[V any] struct {
    56  	head *atomicEntry[V]
    57  	tail atomic.Pointer[atomicEntry[V]]
    58  }
    59  
    60  func (l *atomicList[V]) init() {
    61  	l.head = new(atomicEntry[V])
    62  	l.tail.Store(l.head)
    63  }
    64  
    65  func (l *atomicList[V]) append(v V) *atomicEntry[V] {
    66  	e := &atomicEntry[V]{value: v}
    67  	for {
    68  		tail := l.tail.Load()
    69  		if tail.next.CompareAndSwap(nil, e) {
    70  			l.tail.Store(e)
    71  			return e
    72  		}
    73  	}
    74  }
    75  
    76  type onceFuture struct {
    77  	future.Future[error]
    78  	once atomic.Bool
    79  	next atomic.Pointer[onceFuture]
    80  }
    81  
    82  func (f *onceFuture) Complete(err error) {
    83  	if f.once.CompareAndSwap(false, true) {
    84  		f.Future.Complete(err)
    85  	}
    86  }
    87  
    88  type onceFutures struct {
    89  	head *onceFuture
    90  	tail atomic.Pointer[onceFuture]
    91  }
    92  
    93  func (fs *onceFutures) init() {
    94  	fs.head = new(onceFuture)
    95  	fs.tail.Store(fs.head)
    96  }
    97  
    98  func (fs *onceFutures) append(f future.Future[error]) *onceFuture {
    99  	of := &onceFuture{Future: f}
   100  	for {
   101  		tail := fs.tail.Load()
   102  		if tail.next.CompareAndSwap(nil, of) {
   103  			fs.tail.Store(of)
   104  			return of
   105  		}
   106  	}
   107  }
   108  
   109  func (fs *onceFutures) Complete(err error) {
   110  	for of := fs.head.next.Load(); of != nil; of = of.next.Load() {
   111  		of.Complete(err)
   112  	}
   113  }
   114  
   115  type Lifecycle interface {
   116  	// Run 在当前协程运行生命周期的整体流程,包括启动的过程和运行的过程。当启动失败或运行退出包含
   117  	// 错误信息时,此函数返回此错误。
   118  	Run() error
   119  
   120  	// Start 在当前协程执行生命周期的启动流程,当启动成功后会在新的协程运行此生命周期。当启动失败
   121  	// 时返回错误。
   122  	Start() error
   123  
   124  	// Background 在确定可以启动此生命周期后,使用新的协程运行生命周期的整体流程。返回错误则说明
   125  	// 不能启动。
   126  	Background() error
   127  
   128  	// Close 通知生命周期进行关闭流程,执行此流程返回成功后,生命周期将在清理资源后关闭。
   129  	Close() error
   130  
   131  	// Shutdown 关闭生命周期,如果返回错误,则说明通知生命周期进行关闭失败。否则将等待生命周期完
   132  	// 全关闭
   133  	Shutdown() error
   134  
   135  	// State 返回生命周期的当前状态,详见 State 类型。
   136  	State() State
   137  
   138  	// Future 向生命周期中添加指定类型(详见 FutureType)的 future,用于跟踪生命周期状态的变
   139  	// 化。若生命周期状态已切换到触发状态及以后,则会在此函数中完成指定的 future。
   140  	Future(FutureType, Future) Future
   141  
   142  	// Waiter 获取生命周期状态变化的通知通道。
   143  	Waiter(FutureType) <-chan error
   144  
   145  	//Wait(typ FutureType, interrupter chan struct{}) error
   146  
   147  	Before(BeforeCallbackType, BeforeCallback)
   148  
   149  	After(AfterCallbackType, AfterCallback)
   150  
   151  	OnPanic(PanicCallbackType, PanicCallback)
   152  }
   153  
   154  type DefaultLifecycle struct {
   155  	runner          Runner
   156  	futures         [futureTypes]onceFutures
   157  	beforeCallbacks [beforeCallbackTypes]atomicList[BeforeCallback]
   158  	afterCallbacks  [afterCallbackTypes]atomicList[AfterCallback]
   159  	panicCallback   [panicCallbackTypes]PanicCallback
   160  	state           atomic.Uint32
   161  	startErr        error
   162  	exitErr         error
   163  }
   164  
   165  func New(runner Runner) *DefaultLifecycle {
   166  	if runner == nil {
   167  		runner = NopRunner()
   168  	}
   169  	l := &DefaultLifecycle{runner: runner}
   170  	for i := range l.futures {
   171  		l.futures[i].init()
   172  	}
   173  	for i := range l.beforeCallbacks {
   174  		l.beforeCallbacks[i].init()
   175  	}
   176  	for i := range l.afterCallbacks {
   177  		l.afterCallbacks[i].init()
   178  	}
   179  	return l
   180  }
   181  
   182  func NewWithFunc(startFn StartFunc, runFn RunFunc, closeFn CloseFunc) *DefaultLifecycle {
   183  	return New(FuncRunner(startFn, runFn, closeFn))
   184  }
   185  
   186  func NewInterrupted(runner InterruptedRunner) *DefaultLifecycle {
   187  	return New(WrapInterruptedRunner(runner))
   188  }
   189  
   190  func NewInterruptedWithFunc(startFn InterruptedStartFunc, runFn InterruptedRunFunc) *DefaultLifecycle {
   191  	return New(WrapInterruptedRunner(FuncInterruptedRunner(startFn, runFn)))
   192  }
   193  
   194  func NewInterruptedWithStarter(starter InterruptedStarter) *DefaultLifecycle {
   195  	return New(InterruptedStarterRunner(starter))
   196  }
   197  
   198  func NewInterruptedWithStarterFunc(starterFn InterruptedStarterFunc) *DefaultLifecycle {
   199  	return New(InterruptedStarterRunner(FuncInterruptedStarter(starterFn)))
   200  }
   201  
   202  func (l *DefaultLifecycle) addFuture(typ FutureType, f Future) (*onceFuture, State) {
   203  	return l.futures[typ].append(f), State(l.state.Load())
   204  }
   205  
   206  func (l *DefaultLifecycle) completeFutures(typ FutureType, err error) {
   207  	l.futures[typ].Complete(err)
   208  }
   209  
   210  func (l *DefaultLifecycle) addBeforeCallback(typ BeforeCallbackType, callback BeforeCallback) {
   211  	l.beforeCallbacks[typ].append(callback)
   212  }
   213  
   214  func (l *DefaultLifecycle) executeBeforeCallbacks(typ BeforeCallbackType) error {
   215  	for e := l.beforeCallbacks[typ].head.next.Load(); e != nil; e = e.next.Load() {
   216  		if err := e.value(l); err != nil {
   217  			return err
   218  		}
   219  	}
   220  	return nil
   221  }
   222  
   223  func (l *DefaultLifecycle) addAfterCallback(typ AfterCallbackType, callback AfterCallback) {
   224  	l.afterCallbacks[typ].append(callback)
   225  }
   226  
   227  func (l *DefaultLifecycle) executeAfterCallbacks(typ AfterCallbackType, err error) {
   228  	for e := l.afterCallbacks[typ].head.next.Load(); e != nil; e = e.next.Load() {
   229  		e.value(l, err)
   230  	}
   231  }
   232  
   233  func (l *DefaultLifecycle) loadPanicCallback(typ PanicCallbackType) PanicCallback {
   234  	up := atomic.LoadUintptr((*uintptr)(unsafe.Pointer(&l.panicCallback[typ])))
   235  	return *(*PanicCallback)(unsafe.Pointer(&up))
   236  }
   237  
   238  func (l *DefaultLifecycle) storePanicCallback(typ PanicCallbackType, callback PanicCallback) {
   239  	up := *(*uintptr)(unsafe.Pointer(&callback))
   240  	atomic.StoreUintptr((*uintptr)(unsafe.Pointer(&l.panicCallback[typ])), up)
   241  }
   242  
   243  func (l *DefaultLifecycle) handlePanic(typ PanicCallbackType, ep *error) {
   244  	if callback := l.loadPanicCallback(typ); callback != nil {
   245  		if e := recover(); e != nil {
   246  			*ep = callback(l, e)
   247  		}
   248  	}
   249  	return
   250  }
   251  
   252  func (l *DefaultLifecycle) doStart() (err error) {
   253  	defer l.handlePanic(PanicOnStarting, &err)
   254  	return l.runner.DoStart(l)
   255  }
   256  
   257  func (l *DefaultLifecycle) start() error {
   258  	if l.startErr = l.executeBeforeCallbacks(BeforeStart); l.startErr != nil {
   259  		return l.startErr
   260  	}
   261  	l.startErr = l.doStart()
   262  	l.executeAfterCallbacks(AfterStart, l.startErr)
   263  	if l.startErr != nil {
   264  		l.exitErr = l.startErr
   265  		l.state.Store(uint32(StateClosed))
   266  		l.completeFutures(FutureTypeStarted, l.startErr)
   267  		l.completeFutures(FutureTypeClosed, l.exitErr)
   268  	} else {
   269  		l.state.Store(uint32(StateRunning))
   270  		l.completeFutures(FutureTypeStarted, nil)
   271  	}
   272  	return l.startErr
   273  }
   274  
   275  func (l *DefaultLifecycle) doRun() (err error) {
   276  	defer l.handlePanic(PanicOnRunning, &err)
   277  	return l.runner.DoRun(l)
   278  }
   279  
   280  func (l *DefaultLifecycle) run() error {
   281  	l.exitErr = l.runner.DoRun(l)
   282  	l.executeAfterCallbacks(AfterRun, l.exitErr)
   283  	l.state.Store(uint32(StateClosed))
   284  	l.completeFutures(FutureTypeClosed, nil)
   285  	return l.exitErr
   286  }
   287  
   288  func (l *DefaultLifecycle) Runner() Runner {
   289  	return l.runner
   290  }
   291  
   292  func (l *DefaultLifecycle) Run() error {
   293  	if !l.state.CompareAndSwap(uint32(StateReady), uint32(StateStarting)) {
   294  		return l.waitClosed()
   295  	}
   296  	if err := l.start(); err != nil {
   297  		return err
   298  	}
   299  	return l.run()
   300  }
   301  
   302  func (l *DefaultLifecycle) Start() error {
   303  	if !l.state.CompareAndSwap(uint32(StateReady), uint32(StateStarting)) {
   304  		return l.waitStarted()
   305  	}
   306  	if err := l.start(); err != nil {
   307  		return err
   308  	}
   309  	go l.run()
   310  	return nil
   311  }
   312  
   313  func (l *DefaultLifecycle) Background() error {
   314  	if !l.state.CompareAndSwap(uint32(StateReady), uint32(StateStarting)) {
   315  		return nil
   316  	}
   317  	go func() {
   318  		if err := l.start(); err == nil {
   319  			l.run()
   320  		}
   321  	}()
   322  	return nil
   323  }
   324  
   325  func (l *DefaultLifecycle) Close() error {
   326  	if l.state.CompareAndSwap(uint32(StateReady), uint32(StateClosed)) {
   327  		// 状态为 Ready 则直接转变状态为 Closed,并触发 future
   328  		l.completeFutures(FutureTypeStarted, nil)
   329  		l.completeFutures(FutureTypeClosed, nil)
   330  		return nil
   331  	}
   332  	if state := State(l.state.Load()); state < StateClosed {
   333  		// 状态为 Starting 或 Running,执行 runner 的 DoClose 方法通知生命周期进行关闭
   334  		if err := l.executeBeforeCallbacks(BeforeClose); err != nil {
   335  			return err
   336  		}
   337  		err := l.runner.DoClose(l)
   338  		l.executeAfterCallbacks(AfterClose, err)
   339  		return err
   340  	}
   341  	return nil
   342  }
   343  
   344  func (l *DefaultLifecycle) Shutdown() error {
   345  	if err := l.Close(); err != nil {
   346  		return err
   347  	}
   348  	l.waitClosed()
   349  	return nil
   350  }
   351  
   352  func (l *DefaultLifecycle) State() State {
   353  	return State(l.state.Load())
   354  }
   355  
   356  func (l *DefaultLifecycle) waitStarted() error {
   357  	state := l.State()
   358  	if state > StateStarting {
   359  		return l.startErr
   360  	}
   361  	f := make(future.ChanFuture[error], 1)
   362  	if _, ns := l.addFuture(FutureTypeStarted, f); ns > StateStarting {
   363  		return l.startErr
   364  	} else {
   365  		return <-f
   366  	}
   367  }
   368  
   369  func (l *DefaultLifecycle) waitClosed() error {
   370  	state := l.State()
   371  	if state > StateRunning {
   372  		return l.exitErr
   373  	}
   374  	f := make(future.ChanFuture[error], 1)
   375  	if _, ns := l.addFuture(FutureTypeClosed, f); ns > StateRunning {
   376  		return l.exitErr
   377  	} else {
   378  		return <-f
   379  	}
   380  }
   381  
   382  func (l *DefaultLifecycle) StartedFuture(f Future) Future {
   383  	state := l.State()
   384  	if state > StateStarting {
   385  		// 状态已经高于触发 future 的阈值,不添加到生命周期中,并且立即完成此 future
   386  		f.Complete(l.startErr)
   387  	} else if of, ns := l.addFuture(FutureTypeStarted, f); ns > StateStarting {
   388  		// 在添加 future 时状态发生切换,由于不确定运行协程是否完成此 future,此处需要手
   389  		// 动完成,由 onceFuture 来保证 future 只会被完成一次
   390  		of.Complete(l.startErr)
   391  	} else {
   392  		// 将 future 添加到了生命周期中,并且状态没有切换到高于触发 future 的阈值,由生
   393  		// 命周期运行协程完成此 future
   394  	}
   395  	return f
   396  }
   397  
   398  func (l *DefaultLifecycle) ClosedFuture(f Future) Future {
   399  	state := l.State()
   400  	if state > StateRunning {
   401  		// 状态已经高于触发 future 的阈值,不添加到生命周期中,并且立即完成此 future
   402  		f.Complete(l.exitErr)
   403  	} else if of, ns := l.addFuture(FutureTypeClosed, f); ns > StateRunning {
   404  		// 在添加 future 时状态发生切换,由于不确定运行协程是否完成此 future,此处需要手
   405  		// 动完成,由 onceFuture 来保证 future 只会被完成一次
   406  		of.Complete(l.exitErr)
   407  	} else {
   408  		// 将 future 添加到了生命周期中,并且状态没有切换到高于触发 future 的阈值,由生
   409  		// 命周期运行协程完成此 future
   410  	}
   411  	return f
   412  }
   413  
   414  func (l *DefaultLifecycle) Future(typ FutureType, f Future) Future {
   415  	switch typ {
   416  	case FutureTypeStarted:
   417  		return l.StartedFuture(f)
   418  	case FutureTypeClosed:
   419  		return l.ClosedFuture(f)
   420  	}
   421  	return nil
   422  }
   423  
   424  func (l *DefaultLifecycle) Waiter(typ FutureType) <-chan error {
   425  	if typ < futureTypes {
   426  		waiter := make(future.ChanFuture[error], 1)
   427  		l.Future(typ, waiter)
   428  		return waiter
   429  	}
   430  	return nil
   431  }
   432  
   433  func (l *DefaultLifecycle) Before(typ BeforeCallbackType, callback BeforeCallback) {
   434  	if typ < beforeCallbackTypes {
   435  		l.addBeforeCallback(typ, callback)
   436  	}
   437  }
   438  
   439  func (l *DefaultLifecycle) After(typ AfterCallbackType, callback AfterCallback) {
   440  	if typ < afterCallbackTypes {
   441  		l.addAfterCallback(typ, callback)
   442  	}
   443  }
   444  
   445  func (l *DefaultLifecycle) OnPanic(typ PanicCallbackType, callback PanicCallback) {
   446  	if typ < panicCallbackTypes {
   447  		l.storePanicCallback(typ, callback)
   448  	}
   449  }