diff options
Diffstat (limited to 'vendor/codeberg.org/gruf/go-runners/service.go')
-rw-r--r-- | vendor/codeberg.org/gruf/go-runners/service.go | 159 |
1 files changed, 0 insertions, 159 deletions
diff --git a/vendor/codeberg.org/gruf/go-runners/service.go b/vendor/codeberg.org/gruf/go-runners/service.go deleted file mode 100644 index c0f878c45..000000000 --- a/vendor/codeberg.org/gruf/go-runners/service.go +++ /dev/null @@ -1,159 +0,0 @@ -package runners - -import ( - "context" - "sync" -) - -// 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 -} - -// Run will run the supplied function until completion, use given context to propagate cancel. -// Immediately returns false if the Service is already running, and true after completed run. -func (svc *Service) Run(fn func(context.Context)) bool { - // Attempt to start the svc - ctx, ok := svc.doStart() - if !ok { - return false - } - - defer func() { - // unlock single wait - svc.wait.Unlock() - - // ensure stopped - svc.Stop() - }() - - // Run user func - if fn != nil { - fn(ctx) - } - return true -} - -// Stop will attempt to stop the service, cancelling the running function's context. Immediately -// 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() - if !ok { - return false - } - - defer func() { - // Get svc lock - svc.mu.Lock() - - // Wait until stopped - svc.wait.Lock() - svc.wait.Unlock() - - // Reset the svc - svc.ctx = nil - svc.cncl = nil - svc.state = 0 - svc.mu.Unlock() - }() - - cncl() // cancel ctx - return true -} - -// doStart will safely set Service state to started, returning a ptr to this context insance. -func (svc *Service) doStart() (context.Context, bool) { - // Protect startup - svc.mu.Lock() - - if svc.state != 0 /* not stopped */ { - svc.mu.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() - } - - // Start the waiter - svc.wait.Lock() - - // Set our ptr + unlock - ctx = svc.ctx - svc.mu.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) { - // Protect stop - svc.mu.Lock() - - if svc.state != 1 /* not started */ { - svc.mu.Unlock() - return nil, false - } - - // state stopping - svc.state = 2 - - // Take our own ptr - // and unlock state - cncl := svc.cncl - svc.mu.Unlock() - - return cncl, true -} - -// Running returns if Service is running (i.e. state NOT stopped / stopping). -func (svc *Service) Running() bool { - svc.mu.Lock() - state := svc.state - svc.mu.Unlock() - return (state == 1) -} - -// Done returns a channel that's closed when Service.Stop() is called. It is -// the same channel provided to the currently running service function. -func (svc *Service) Done() <-chan struct{} { - var done <-chan struct{} - - svc.mu.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() - } - done = svc.ctx.Done() - - // started - case 1: - done = svc.ctx.Done() - - // stopping - case 2: - done = svc.ctx.Done() - } - svc.mu.Unlock() - - return done -} |