mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	* Dropped unused codekit config * Integrated dynamic and static bindata for public * Ignore public bindata * Add a general generate make task * Integrated flexible public assets into web command * Updated vendoring, added all missiong govendor deps * Made the linter happy with the bindata and dynamic code * Moved public bindata definition to modules directory * Ignoring the new bindata path now * Updated to the new public modules import path * Updated public bindata command and drop the new prefix
		
			
				
	
	
		
			122 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			122 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2013, Google Inc. All rights reserved.
 | 
						|
// Use of this source code is governed by a BSD-style
 | 
						|
// license that can be found in the LICENSE file.
 | 
						|
 | 
						|
package sync2
 | 
						|
 | 
						|
import (
 | 
						|
	"sync"
 | 
						|
)
 | 
						|
 | 
						|
// These are the three predefined states of a service.
 | 
						|
const (
 | 
						|
	SERVICE_STOPPED = iota
 | 
						|
	SERVICE_RUNNING
 | 
						|
	SERVICE_SHUTTING_DOWN
 | 
						|
)
 | 
						|
 | 
						|
var stateNames = []string{
 | 
						|
	"Stopped",
 | 
						|
	"Running",
 | 
						|
	"ShuttingDown",
 | 
						|
}
 | 
						|
 | 
						|
// ServiceManager manages the state of a service through its lifecycle.
 | 
						|
type ServiceManager struct {
 | 
						|
	mu    sync.Mutex
 | 
						|
	wg    sync.WaitGroup
 | 
						|
	err   error // err is the error returned from the service function.
 | 
						|
	state AtomicInt64
 | 
						|
	// shutdown is created when the service starts and is closed when the service
 | 
						|
	// enters the SERVICE_SHUTTING_DOWN state.
 | 
						|
	shutdown chan struct{}
 | 
						|
}
 | 
						|
 | 
						|
// Go tries to change the state from SERVICE_STOPPED to SERVICE_RUNNING.
 | 
						|
//
 | 
						|
// If the current state is not SERVICE_STOPPED (already running), it returns
 | 
						|
// false immediately.
 | 
						|
//
 | 
						|
// On successful transition, it launches the service as a goroutine and returns
 | 
						|
// true. The service function is responsible for returning on its own when
 | 
						|
// requested, either by regularly checking svc.IsRunning(), or by waiting for
 | 
						|
// the svc.ShuttingDown channel to be closed.
 | 
						|
//
 | 
						|
// When the service func returns, the state is reverted to SERVICE_STOPPED.
 | 
						|
func (svm *ServiceManager) Go(service func(svc *ServiceContext) error) bool {
 | 
						|
	svm.mu.Lock()
 | 
						|
	defer svm.mu.Unlock()
 | 
						|
	if !svm.state.CompareAndSwap(SERVICE_STOPPED, SERVICE_RUNNING) {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	svm.wg.Add(1)
 | 
						|
	svm.err = nil
 | 
						|
	svm.shutdown = make(chan struct{})
 | 
						|
	go func() {
 | 
						|
		svm.err = service(&ServiceContext{ShuttingDown: svm.shutdown})
 | 
						|
		svm.state.Set(SERVICE_STOPPED)
 | 
						|
		svm.wg.Done()
 | 
						|
	}()
 | 
						|
	return true
 | 
						|
}
 | 
						|
 | 
						|
// Stop tries to change the state from SERVICE_RUNNING to SERVICE_SHUTTING_DOWN.
 | 
						|
// If the current state is not SERVICE_RUNNING, it returns false immediately.
 | 
						|
// On successul transition, it waits for the service to finish, and returns true.
 | 
						|
// You are allowed to Go() again after a Stop().
 | 
						|
func (svm *ServiceManager) Stop() bool {
 | 
						|
	svm.mu.Lock()
 | 
						|
	defer svm.mu.Unlock()
 | 
						|
	if !svm.state.CompareAndSwap(SERVICE_RUNNING, SERVICE_SHUTTING_DOWN) {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	// Signal the service that we've transitioned to SERVICE_SHUTTING_DOWN.
 | 
						|
	close(svm.shutdown)
 | 
						|
	svm.shutdown = nil
 | 
						|
	svm.wg.Wait()
 | 
						|
	return true
 | 
						|
}
 | 
						|
 | 
						|
// Wait waits for the service to terminate if it's currently running.
 | 
						|
func (svm *ServiceManager) Wait() {
 | 
						|
	svm.wg.Wait()
 | 
						|
}
 | 
						|
 | 
						|
// Join waits for the service to terminate and returns the value returned by the
 | 
						|
// service function.
 | 
						|
func (svm *ServiceManager) Join() error {
 | 
						|
	svm.wg.Wait()
 | 
						|
	return svm.err
 | 
						|
}
 | 
						|
 | 
						|
// State returns the current state of the service.
 | 
						|
// This should only be used to report the current state.
 | 
						|
func (svm *ServiceManager) State() int64 {
 | 
						|
	return svm.state.Get()
 | 
						|
}
 | 
						|
 | 
						|
// StateName returns the name of the current state.
 | 
						|
func (svm *ServiceManager) StateName() string {
 | 
						|
	return stateNames[svm.State()]
 | 
						|
}
 | 
						|
 | 
						|
// ServiceContext is passed into the service function to give it access to
 | 
						|
// information about the running service.
 | 
						|
type ServiceContext struct {
 | 
						|
	// ShuttingDown is a channel that the service can select on to be notified
 | 
						|
	// when it should shut down. The channel is closed when the state transitions
 | 
						|
	// from SERVICE_RUNNING to SERVICE_SHUTTING_DOWN.
 | 
						|
	ShuttingDown chan struct{}
 | 
						|
}
 | 
						|
 | 
						|
// IsRunning returns true if the ServiceContext.ShuttingDown channel has not
 | 
						|
// been closed yet.
 | 
						|
func (svc *ServiceContext) IsRunning() bool {
 | 
						|
	select {
 | 
						|
	case <-svc.ShuttingDown:
 | 
						|
		return false
 | 
						|
	default:
 | 
						|
		return true
 | 
						|
	}
 | 
						|
}
 |