145 lines
2.5 KiB
Go
145 lines
2.5 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 windows
|
|
// +build windows
|
|
|
|
package nbio
|
|
|
|
import (
|
|
"net"
|
|
"runtime"
|
|
"time"
|
|
|
|
"github.com/lesismal/nbio/logging"
|
|
)
|
|
|
|
const (
|
|
// EPOLLLT .
|
|
EPOLLLT = 0
|
|
|
|
// EPOLLET .
|
|
EPOLLET = 1
|
|
)
|
|
|
|
type poller struct {
|
|
g *Gopher
|
|
|
|
index int
|
|
|
|
ReadBuffer []byte
|
|
|
|
pollType string
|
|
isListener bool
|
|
listener net.Listener
|
|
shutdown bool
|
|
|
|
chStop chan struct{}
|
|
}
|
|
|
|
func (p *poller) accept() error {
|
|
conn, err := p.listener.Accept()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
c := newConn(conn)
|
|
o := p.g.pollers[c.Hash()%len(p.g.pollers)]
|
|
o.addConn(c)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (p *poller) readConn(c *Conn) {
|
|
for {
|
|
buffer := p.g.borrow(c)
|
|
_, err := c.read(buffer)
|
|
p.g.payback(c, buffer)
|
|
if err != nil {
|
|
c.Close()
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func (p *poller) addConn(c *Conn) error {
|
|
c.g = p.g
|
|
p.g.mux.Lock()
|
|
p.g.connsStd[c] = struct{}{}
|
|
p.g.mux.Unlock()
|
|
p.g.onOpen(c)
|
|
go p.readConn(c)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (p *poller) deleteConn(c *Conn) {
|
|
p.g.mux.Lock()
|
|
delete(p.g.connsStd, c)
|
|
p.g.mux.Unlock()
|
|
p.g.onClose(c, c.closeErr)
|
|
}
|
|
|
|
func (p *poller) start() {
|
|
if p.g.lockListener {
|
|
runtime.LockOSThread()
|
|
defer runtime.UnlockOSThread()
|
|
}
|
|
defer p.g.Done()
|
|
|
|
logging.Debug("Poller[%v_%v_%v] start", p.g.Name, p.pollType, p.index)
|
|
defer logging.Debug("Poller[%v_%v_%v] stopped", p.g.Name, p.pollType, p.index)
|
|
|
|
if p.isListener {
|
|
var err error
|
|
p.shutdown = false
|
|
for !p.shutdown {
|
|
err = p.accept()
|
|
if err != nil {
|
|
if ne, ok := err.(net.Error); ok && ne.Temporary() {
|
|
logging.Error("Poller[%v_%v_%v] Accept failed: temporary error, retrying...", p.g.Name, p.pollType, p.index)
|
|
time.Sleep(time.Second / 20)
|
|
} else {
|
|
logging.Error("Poller[%v_%v_%v] Accept failed: %v, exit...", p.g.Name, p.pollType, p.index, err)
|
|
break
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
<-p.chStop
|
|
}
|
|
|
|
func (p *poller) stop() {
|
|
logging.Debug("Poller[%v_%v_%v] stop...", p.g.Name, p.pollType, p.index)
|
|
p.shutdown = true
|
|
if p.isListener {
|
|
p.listener.Close()
|
|
}
|
|
close(p.chStop)
|
|
}
|
|
|
|
func newPoller(g *Gopher, isListener bool, index int) (*poller, error) {
|
|
p := &poller{
|
|
g: g,
|
|
index: index,
|
|
isListener: isListener,
|
|
chStop: make(chan struct{}),
|
|
}
|
|
|
|
if isListener {
|
|
var err error
|
|
var addr = g.addrs[index%len(g.addrs)]
|
|
p.listener, err = net.Listen(g.network, addr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
p.pollType = "LISTENER"
|
|
} else {
|
|
p.pollType = "POLLER"
|
|
}
|
|
|
|
return p, nil
|
|
}
|