func (gs *Server) FinishRoutine() {
	gs.wg.Done()
	atomic.AddInt32(&gs.routinesCount, -1)
}
FinishRoutine decrements the server's WaitGroup. Use this to complement
StartRoutine().
package graceful
import (
	"crypto/tls"
	"net"
	"net/http"
	"os"
	"sync"
	"sync/atomic"
	"unsafe"
)
type StateHandler func(net.Conn, http.ConnState, http.ConnState)
type Options struct {
	Server       *http.Server
	StateHandler StateHandler
	Listener     net.Listener
}
type Server struct {
	*http.Server
	shutdown         chan bool
	shutdownFinished chan bool
	wg               *sync.WaitGroup
	routinesCount    int32
	listener         *Listener
	stateHandler     StateHandler
	connToProps      map[net.Conn]connProperties
	connToPropsMtx   sync.RWMutex
	up chan net.Listener  
}
func NewServer() *Server {
	return NewWithOptions(Options{})
}
func NewWithServer(s *http.Server) *Server {
	return NewWithOptions(Options{Server: s})
}
func NewWithOptions(o Options) *Server {
	var listener *Listener
	if o.Listener != nil {
		g, ok := o.Listener.(*Listener)
		if !ok {
			listener = NewListener(o.Listener)
		} else {
			listener = g
		}
	}
	if o.Server == nil {
		o.Server = new(http.Server)
	}
	return &Server{
		Server:           o.Server,
		listener:         listener,
		stateHandler:     o.StateHandler,
		shutdown:         make(chan bool),
		shutdownFinished: make(chan bool, 1),
		wg:               new(sync.WaitGroup),
		connToProps:      make(map[net.Conn]connProperties),
	}
}
func (gs *Server) Close() bool {
	return <-gs.shutdown
}
func (gs *Server) BlockingClose() bool {
	result := gs.Close()
	<-gs.shutdownFinished
	return result
}
func (gs *Server) ListenAndServe() error {
	if gs.listener == nil {
		oldListener, err := net.Listen("tcp", gs.Addr)
		if err != nil {
			return err
		}
		gs.listener = NewListener(oldListener.(*net.TCPListener))
	}
	return gs.Serve(gs.listener)
}
func (gs *Server) ListenAndServeTLS(certFile, keyFile string) error {
	addr := gs.Addr
	if addr == "" {
		addr = ":https"
	}
	config := &tls.Config{}
	if gs.TLSConfig != nil {
		*config = *gs.TLSConfig
	}
	if config.NextProtos == nil {
		config.NextProtos = []string{"h2", "http/1.1"}
	}
	var err error
	config.Certificates = make([]tls.Certificate, 1)
	config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
	if err != nil {
		return err
	}
	return gs.ListenAndServeTLSWithConfig(config)
}
func (gs *Server) ListenAndServeTLSWithConfig(config *tls.Config) error {
	addr := gs.Addr
	if addr == "" {
		addr = ":https"
	}
	if gs.listener == nil {
		ln, err := net.Listen("tcp", addr)
		if err != nil {
			return err
		}
		tlsListener := NewTLSListener(TCPKeepAliveListener{ln.(*net.TCPListener)}, config)
		gs.listener = NewListener(tlsListener)
	}
	return gs.Serve(gs.listener)
}
func (gs *Server) GetFile() (*os.File, error) {
	return gs.listener.GetFile()
}
type ListenerMutateFunc func(net.Listener) (net.Listener, error)
func (gs *Server) HijackListener(s *http.Server, fn ListenerMutateFunc) (*Server, error) {
	listenerUnsafePtr := unsafe.Pointer(gs.listener)
	listener, err := (*Listener)(atomic.LoadPointer(&listenerUnsafePtr)).Clone()
	if err != nil {
		return nil, err
	}
	if fn != nil {
		listener, err = fn(listener)
		if err != nil {
			return nil, err
		}
	}
	other := NewWithServer(s)
	other.listener = NewListener(listener)
	return other, nil
}
func (gs *Server) Serve(listener net.Listener) error {
	gracefulListener, ok := listener.(*Listener)
	if !ok {
		gracefulListener = NewListener(listener)
		listener = gracefulListener
	}
	listenerUnsafePtr := unsafe.Pointer(gs.listener)
	atomic.StorePointer(&listenerUnsafePtr, unsafe.Pointer(gracefulListener))
	gracefulHandler := newGracefulHandler(gs.Server.Handler)
	gs.Server.Handler = gracefulHandler
	go func() {
		gs.shutdown <- true
		close(gs.shutdown)
		gracefulHandler.Close()
		gs.Server.SetKeepAlivesEnabled(false)
		gracefulListener.Close()
	}()
	originalConnState := gs.Server.ConnState
	gs.ConnState = func(conn net.Conn, newState http.ConnState) {
		gs.connToPropsMtx.RLock()
		connProps := gs.connToProps[conn]
		gs.connToPropsMtx.RUnlock()
		switch newState {
		case http.StateNew:
			connProps.protected = true
			gs.StartRoutine()
		case http.StateActive:
			if gracefulHandler.IsClosed() {
				conn.Close()
				break
			}
			if !connProps.protected {
				connProps.protected = true
				gs.StartRoutine()
			}
		default:
			if connProps.protected {
				gs.FinishRoutine()
				connProps.protected = false
			}
		}
		if gs.stateHandler != nil {
			gs.stateHandler(conn, connProps.state, newState)
		}
		connProps.state = newState
		gs.connToPropsMtx.Lock()
		if newState == http.StateClosed || newState == http.StateHijacked {
			delete(gs.connToProps, conn)
		} else {
			gs.connToProps[conn] = connProps
		}
		gs.connToPropsMtx.Unlock()
		if originalConnState != nil {
			originalConnState(conn, newState)
		}
	}
	if gs.up != nil {
		gs.up <- listener
	}
	err := gs.Server.Serve(listener)
	if err != nil && gracefulHandler.IsClosed() {
		err = nil
	}
	gs.wg.Wait()
	gs.shutdownFinished <- true
	return err
}
func (gs *Server) StartRoutine() {
	gs.wg.Add(1)
	atomic.AddInt32(&gs.routinesCount, 1)
}