123 lines
2.9 KiB
Go
123 lines
2.9 KiB
Go
// Copyright 2020 lesismal. All rights reserved.
|
|
// Use of this source code is governed by an MIT-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
//go:build linux || darwin || netbsd || freebsd || openbsd || dragonfly
|
|
// +build linux darwin netbsd freebsd openbsd dragonfly
|
|
|
|
package nbio
|
|
|
|
import (
|
|
"runtime"
|
|
"strings"
|
|
"syscall"
|
|
"time"
|
|
|
|
"github.com/lesismal/nbio/logging"
|
|
)
|
|
|
|
// Start init and start pollers.
|
|
func (g *Gopher) Start() error {
|
|
var err error
|
|
|
|
for i := 0; i < len(g.addrs); i++ {
|
|
g.listeners[i], err = newPoller(g, true, i)
|
|
if err != nil {
|
|
for j := 0; j < i; j++ {
|
|
g.listeners[j].stop()
|
|
}
|
|
return err
|
|
}
|
|
}
|
|
|
|
for i := 0; i < g.pollerNum; i++ {
|
|
g.pollers[i], err = newPoller(g, false, i)
|
|
if err != nil {
|
|
for j := 0; j < len(g.lfds); j++ {
|
|
syscall.Close(g.lfds[j])
|
|
}
|
|
|
|
for j := 0; j < len(g.listeners); j++ {
|
|
g.listeners[j].stop()
|
|
}
|
|
|
|
for j := 0; j < i; j++ {
|
|
g.pollers[j].stop()
|
|
}
|
|
return err
|
|
}
|
|
}
|
|
|
|
for i := 0; i < g.pollerNum; i++ {
|
|
g.pollers[i].ReadBuffer = make([]byte, g.readBufferSize)
|
|
g.Add(1)
|
|
go g.pollers[i].start()
|
|
}
|
|
for _, l := range g.listeners {
|
|
g.Add(1)
|
|
go l.start()
|
|
}
|
|
|
|
g.Add(1)
|
|
go g.timerLoop()
|
|
|
|
if len(g.addrs) == 0 {
|
|
logging.Info("Gopher[%v] start", g.Name)
|
|
} else {
|
|
logging.Info("Gopher[%v] start listen on: [\"%v\"]", g.Name, strings.Join(g.addrs, `", "`))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// NewGopher is a factory impl.
|
|
func NewGopher(conf Config) *Gopher {
|
|
cpuNum := runtime.NumCPU()
|
|
if conf.Name == "" {
|
|
conf.Name = "NB"
|
|
}
|
|
if conf.NPoller <= 0 {
|
|
conf.NPoller = cpuNum
|
|
}
|
|
if len(conf.Addrs) > 0 && conf.NListener <= 0 {
|
|
conf.NListener = 1
|
|
}
|
|
if conf.Backlog <= 0 {
|
|
conf.Backlog = 1024 * 64
|
|
}
|
|
if conf.ReadBufferSize <= 0 {
|
|
conf.ReadBufferSize = DefaultReadBufferSize
|
|
}
|
|
if conf.MinConnCacheSize == 0 {
|
|
conf.MinConnCacheSize = DefaultMinConnCacheSize
|
|
}
|
|
if conf.MaxReadTimesPerEventLoop <= 0 {
|
|
conf.MaxReadTimesPerEventLoop = DefaultMaxReadTimesPerEventLoop
|
|
}
|
|
|
|
g := &Gopher{
|
|
Name: conf.Name,
|
|
network: conf.Network,
|
|
addrs: conf.Addrs,
|
|
pollerNum: conf.NPoller,
|
|
backlogSize: conf.Backlog,
|
|
readBufferSize: conf.ReadBufferSize,
|
|
maxWriteBufferSize: conf.MaxWriteBufferSize,
|
|
maxReadTimesPerEventLoop: conf.MaxReadTimesPerEventLoop,
|
|
minConnCacheSize: conf.MinConnCacheSize,
|
|
epollMod: conf.EpollMod,
|
|
lockListener: conf.LockListener,
|
|
lockPoller: conf.LockPoller,
|
|
listeners: make([]*poller, len(conf.Addrs)),
|
|
pollers: make([]*poller, conf.NPoller),
|
|
connsUnix: make([]*Conn, MaxOpenFiles),
|
|
callings: []func(){},
|
|
chCalling: make(chan struct{}, 1),
|
|
trigger: time.NewTimer(timeForever),
|
|
chTimer: make(chan struct{}),
|
|
}
|
|
|
|
g.initHandlers()
|
|
|
|
return g
|
|
}
|