diff options
author | 2023-01-06 10:16:09 +0000 | |
---|---|---|
committer | 2023-01-06 11:16:09 +0100 | |
commit | adbc87700a5bc7a95883ba5b9688d8b946a8db48 (patch) | |
tree | 6030ff70d3eb0b9a0b8fc7d5fca378a77033d546 /vendor/codeberg.org/gruf/go-runners/service.go | |
parent | [chore] Update/add license headers for 2023 (#1304) (diff) | |
download | gotosocial-adbc87700a5bc7a95883ba5b9688d8b946a8db48.tar.xz |
[chore] pull in latest go-cache, go-runners versions (#1306)
Signed-off-by: kim <grufwub@gmail.com>
Signed-off-by: kim <grufwub@gmail.com>
Diffstat (limited to 'vendor/codeberg.org/gruf/go-runners/service.go')
-rw-r--r-- | vendor/codeberg.org/gruf/go-runners/service.go | 105 |
1 files changed, 56 insertions, 49 deletions
diff --git a/vendor/codeberg.org/gruf/go-runners/service.go b/vendor/codeberg.org/gruf/go-runners/service.go index 68e8ea384..2c9be8225 100644 --- a/vendor/codeberg.org/gruf/go-runners/service.go +++ b/vendor/codeberg.org/gruf/go-runners/service.go @@ -8,11 +8,10 @@ import ( // Service provides a means of tracking a single long-running service, provided protected state // changes and preventing multiple instances running. Also providing service state information. type Service struct { - state uint32 // 0=stopped, 1=running, 2=stopping - wait sync.Mutex // wait is the mutex used as a single-entity wait-group, i.e. just a "wait" :p - cncl context.CancelFunc // cncl is the cancel function set for the current context - ctx context.Context // ctx is the current context for running function (or nil if not running) - mu sync.Mutex // mu protects state changes + state uint32 // 0=stopped, 1=running, 2=stopping + mutex sync.Mutex // mutext protects overall state changes + wait sync.Mutex // wait is used as a single-entity wait-group, only ever locked within 'mutex' + ctx cancelctx // ctx is the current context for running function (or nil if not running) } // Run will run the supplied function until completion, using given context to propagate cancel. @@ -29,13 +28,12 @@ func (svc *Service) Run(fn func(context.Context)) bool { svc.wait.Unlock() // ensure stopped - svc.Stop() + _ = svc.Stop() }() - // Run user func - if fn != nil { - fn(ctx) - } + // Run + fn(ctx) + return true } @@ -54,13 +52,11 @@ func (svc *Service) GoRun(fn func(context.Context)) bool { svc.wait.Unlock() // ensure stopped - svc.Stop() + _ = svc.Stop() }() - // Run user func - if fn != nil { - fn(ctx) - } + // Run + fn(ctx) }() return true @@ -70,14 +66,14 @@ func (svc *Service) GoRun(fn func(context.Context)) bool { // returns false if not running, and true only after Service is fully stopped. func (svc *Service) Stop() bool { // Attempt to stop the svc - cncl, ok := svc.doStop() + ctx, ok := svc.doStop() if !ok { return false } defer func() { // Get svc lock - svc.mu.Lock() + svc.mutex.Lock() // Wait until stopped svc.wait.Lock() @@ -85,53 +81,65 @@ func (svc *Service) Stop() bool { // Reset the svc svc.ctx = nil - svc.cncl = nil svc.state = 0 - svc.mu.Unlock() + svc.mutex.Unlock() }() - cncl() // cancel ctx + // Cancel ctx + close(ctx) + return true } +// While allows you to execute given function guaranteed within current +// service state. Please note that this will hold the underlying service +// state change mutex open while executing the function. +func (svc *Service) While(fn func()) { + // Protect state change + svc.mutex.Lock() + defer svc.mutex.Unlock() + + // Run + fn() +} + // doStart will safely set Service state to started, returning a ptr to this context insance. -func (svc *Service) doStart() (context.Context, bool) { +func (svc *Service) doStart() (cancelctx, bool) { // Protect startup - svc.mu.Lock() + svc.mutex.Lock() if svc.state != 0 /* not stopped */ { - svc.mu.Unlock() + svc.mutex.Unlock() return nil, false } // state started svc.state = 1 - // Take our own ptr - var ctx context.Context - if svc.ctx == nil { - // Context required allocating - svc.ctx, svc.cncl = ContextWithCancel() + // this will only have been allocated + // if svc.Done() was already called. + svc.ctx = make(cancelctx) } // Start the waiter svc.wait.Lock() - // Set our ptr + unlock - ctx = svc.ctx - svc.mu.Unlock() + // Take our own ptr + // and unlock state + ctx := svc.ctx + svc.mutex.Unlock() return ctx, true } // doStop will safely set Service state to stopping, returning a ptr to this cancelfunc instance. -func (svc *Service) doStop() (context.CancelFunc, bool) { +func (svc *Service) doStop() (cancelctx, bool) { // Protect stop - svc.mu.Lock() + svc.mutex.Lock() if svc.state != 1 /* not started */ { - svc.mu.Unlock() + svc.mutex.Unlock() return nil, false } @@ -140,17 +148,17 @@ func (svc *Service) doStop() (context.CancelFunc, bool) { // Take our own ptr // and unlock state - cncl := svc.cncl - svc.mu.Unlock() + ctx := svc.ctx + svc.mutex.Unlock() - return cncl, true + return ctx, true } // Running returns if Service is running (i.e. state NOT stopped / stopping). func (svc *Service) Running() bool { - svc.mu.Lock() + svc.mutex.Lock() state := svc.state - svc.mu.Unlock() + svc.mutex.Unlock() return (state == 1) } @@ -159,28 +167,27 @@ func (svc *Service) Running() bool { func (svc *Service) Done() <-chan struct{} { var done <-chan struct{} - svc.mu.Lock() + svc.mutex.Lock() switch svc.state { // stopped - // (here we create a new context so that the - // returned 'done' channel here will still - // be valid for when Service is next started) case 0: if svc.ctx == nil { - // need to allocate new context - svc.ctx, svc.cncl = ContextWithCancel() + // here we create a new context so that the + // returned 'done' channel here will still + // be valid for when Service is next started. + svc.ctx = make(cancelctx) } - done = svc.ctx.Done() + done = svc.ctx // started case 1: - done = svc.ctx.Done() + done = svc.ctx // stopping case 2: - done = svc.ctx.Done() + done = svc.ctx } - svc.mu.Unlock() + svc.mutex.Unlock() return done } |