github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/net/server_windows.go (about)

     1  // +build windows
     2  
     3  package net
     4  
     5  import (
     6  	"errors"
     7  	"os"
     8  	"os/signal"
     9  	"runtime"
    10  	"sync"
    11  	"syscall"
    12  	"time"
    13  )
    14  
    15  // commandBufferSize represents the buffer size of event-loop command channel on Windows.
    16  const (
    17  	commandBufferSize = 512
    18  )
    19  
    20  var errCloseAllConns = errors.New("close all connections in event-loop")
    21  
    22  type server struct {
    23  	ln              *listener          // all the listeners
    24  	cond            *sync.Cond         // shutdown signaler
    25  	opts            *Options           // options with server
    26  	serr            error              // signal error
    27  	once            sync.Once          // make sure only signalShutdown once
    28  	codec           ICodec             // codec for TCP stream
    29  	loopWG          sync.WaitGroup     // loop close WaitGroup
    30  	logger          Logger             // customized logger for logging info
    31  	ticktock        chan time.Duration // ticker channel
    32  	listenerWG      sync.WaitGroup     // listener close WaitGroup
    33  	eventHandler    EventHandler       // user eventHandler
    34  	subEventLoopSet loadBalancer       // event-loops for handling events
    35  }
    36  
    37  // waitForShutdown waits for a signal to shutdown.
    38  func (svr *server) waitForShutdown() error {
    39  	svr.cond.L.Lock()
    40  	svr.cond.Wait()
    41  	err := svr.serr
    42  	svr.cond.L.Unlock()
    43  	return err
    44  }
    45  
    46  // signalShutdown signals a shutdown an begins server closing.
    47  func (svr *server) signalShutdown(err error) {
    48  	svr.once.Do(func() {
    49  		svr.cond.L.Lock()
    50  		svr.serr = err
    51  		svr.cond.Signal()
    52  		svr.cond.L.Unlock()
    53  	})
    54  }
    55  
    56  func (svr *server) startListener() {
    57  	svr.listenerWG.Add(1)
    58  	go func() {
    59  		svr.listenerRun()
    60  		svr.listenerWG.Done()
    61  	}()
    62  }
    63  
    64  func (svr *server) startLoops(numEventLoop int) {
    65  	for i := 0; i < numEventLoop; i++ {
    66  		el := &eventloop{
    67  			ch:                make(chan interface{}, commandBufferSize),
    68  			svr:               svr,
    69  			codec:             svr.codec,
    70  			connections:       make(map[*stdConn]struct{}),
    71  			eventHandler:      svr.eventHandler,
    72  			calibrateCallback: svr.subEventLoopSet.calibrate,
    73  		}
    74  		svr.subEventLoopSet.register(el)
    75  	}
    76  
    77  	svr.loopWG.Add(svr.subEventLoopSet.len())
    78  	svr.subEventLoopSet.iterate(func(i int, el *eventloop) bool {
    79  		go el.loopRun()
    80  		return true
    81  	})
    82  }
    83  
    84  func (svr *server) stop() {
    85  	// Wait on a signal for shutdown.
    86  	svr.logger.Printf("server is being shutdown with err: %v\n", svr.waitForShutdown())
    87  
    88  	// Close listener.
    89  	svr.ln.close()
    90  	svr.listenerWG.Wait()
    91  
    92  	// Notify all loops to close.
    93  	svr.subEventLoopSet.iterate(func(i int, el *eventloop) bool {
    94  		el.ch <- errServerShutdown
    95  		return true
    96  	})
    97  
    98  	// Wait on all loops to close.
    99  	svr.loopWG.Wait()
   100  
   101  	// Close all connections.
   102  	svr.loopWG.Add(svr.subEventLoopSet.len())
   103  	svr.subEventLoopSet.iterate(func(i int, el *eventloop) bool {
   104  		el.ch <- errCloseAllConns
   105  		return true
   106  	})
   107  	svr.loopWG.Wait()
   108  }
   109  
   110  func serve(eventHandler EventHandler, listener *listener, options *Options) (err error) {
   111  	// Figure out the correct number of loops/goroutines to use.
   112  	numEventLoop := 1
   113  	if options.Multicore {
   114  		numEventLoop = runtime.NumCPU()
   115  	}
   116  	if options.NumEventLoop > 0 {
   117  		numEventLoop = options.NumEventLoop
   118  	}
   119  
   120  	svr := new(server)
   121  	svr.opts = options
   122  	svr.eventHandler = eventHandler
   123  	svr.ln = listener
   124  
   125  	switch options.LB {
   126  	case RoundRobin:
   127  		svr.subEventLoopSet = new(roundRobinEventLoopSet)
   128  	case LeastConnections:
   129  		svr.subEventLoopSet = new(leastConnectionsEventLoopSet)
   130  	case SourceAddrHash:
   131  		svr.subEventLoopSet = new(sourceAddrHashEventLoopSet)
   132  	}
   133  
   134  	svr.ticktock = make(chan time.Duration, 1)
   135  	svr.cond = sync.NewCond(&sync.Mutex{})
   136  	svr.logger = func() Logger {
   137  		if options.Logger == nil {
   138  			return defaultLogger
   139  		}
   140  		return options.Logger
   141  	}()
   142  	svr.codec = func() ICodec {
   143  		if options.Codec == nil {
   144  			return new(BuiltInFrameCodec)
   145  		}
   146  		return options.Codec
   147  	}()
   148  
   149  	server := Server{
   150  		svr:          svr,
   151  		Multicore:    options.Multicore,
   152  		Addr:         listener.lnaddr,
   153  		NumEventLoop: numEventLoop,
   154  		ReusePort:    options.ReusePort,
   155  		TCPKeepAlive: options.TCPKeepAlive,
   156  	}
   157  	switch svr.eventHandler.OnInitComplete(server) {
   158  	case None:
   159  	case Shutdown:
   160  		return
   161  	}
   162  	defer svr.eventHandler.OnShutdown(server)
   163  
   164  	shutdown := make(chan os.Signal, 1)
   165  	signal.Notify(shutdown, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
   166  	defer close(shutdown)
   167  
   168  	go func() {
   169  		if <-shutdown == nil {
   170  			return
   171  		}
   172  		svr.signalShutdown(errors.New("caught OS signal"))
   173  	}()
   174  
   175  	// Start all loops.
   176  	svr.startLoops(numEventLoop)
   177  	// Start listener.
   178  	svr.startListener()
   179  	defer svr.stop()
   180  
   181  	return
   182  }