Simplify ring consumer goroutine
Since network.history is now only accessed from the user goroutine, a lock becomes unnecessary.
This commit is contained in:
parent
10da094259
commit
d4de60a869
@ -71,6 +71,8 @@ type downstreamConn struct {
|
||||
password string // empty after authentication
|
||||
network *network // can be nil
|
||||
|
||||
ringConsumers map[*network]*RingConsumer
|
||||
|
||||
negociatingCaps bool
|
||||
capVersion int
|
||||
caps map[string]bool
|
||||
@ -90,6 +92,7 @@ func newDownstreamConn(srv *Server, netConn net.Conn, id uint64) *downstreamConn
|
||||
logger: &prefixLogger{srv.Logger, fmt.Sprintf("downstream %q: ", netConn.RemoteAddr())},
|
||||
outgoing: make(chan *irc.Message, 64),
|
||||
closed: make(chan struct{}),
|
||||
ringConsumers: make(map[*network]*RingConsumer),
|
||||
caps: make(map[string]bool),
|
||||
ourMessages: make(map[*irc.Message]struct{}),
|
||||
}
|
||||
@ -722,9 +725,7 @@ func (dc *downstreamConn) runNetwork(net *network, loadHistory bool) {
|
||||
|
||||
var seqPtr *uint64
|
||||
if loadHistory {
|
||||
net.lock.Lock()
|
||||
seq, ok := net.history[dc.clientName]
|
||||
net.lock.Unlock()
|
||||
if ok {
|
||||
seqPtr = &seq
|
||||
}
|
||||
@ -735,20 +736,18 @@ func (dc *downstreamConn) runNetwork(net *network, loadHistory bool) {
|
||||
serverTimeEnabled := dc.caps["server-time"]
|
||||
|
||||
consumer, ch := net.ring.NewConsumer(seqPtr)
|
||||
go func() {
|
||||
for {
|
||||
var closed bool
|
||||
select {
|
||||
case _, ok := <-ch:
|
||||
if !ok {
|
||||
closed = true
|
||||
break
|
||||
}
|
||||
|
||||
if _, ok := dc.ringConsumers[net]; ok {
|
||||
panic("network has been added twice")
|
||||
}
|
||||
dc.ringConsumers[net] = consumer
|
||||
|
||||
go func() {
|
||||
for range ch {
|
||||
uc := net.upstream()
|
||||
if uc == nil {
|
||||
dc.logger.Printf("ignoring messages for upstream %q: upstream is disconnected", net.Addr)
|
||||
break
|
||||
continue
|
||||
}
|
||||
|
||||
for {
|
||||
@ -793,21 +792,7 @@ func (dc *downstreamConn) runNetwork(net *network, loadHistory bool) {
|
||||
dc.SendMessage(msg)
|
||||
consumer.Consume()
|
||||
}
|
||||
case <-dc.closed:
|
||||
closed = true
|
||||
}
|
||||
if closed {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: close the consumer from the user goroutine, so we don't need
|
||||
// that net.history lock
|
||||
seq := consumer.Close()
|
||||
|
||||
net.lock.Lock()
|
||||
net.history[dc.clientName] = seq
|
||||
net.lock.Unlock()
|
||||
}()
|
||||
}
|
||||
|
||||
|
9
user.go
9
user.go
@ -41,9 +41,10 @@ type network struct {
|
||||
ring *Ring
|
||||
stopped chan struct{}
|
||||
|
||||
history map[string]uint64
|
||||
|
||||
lock sync.Mutex
|
||||
conn *upstreamConn
|
||||
history map[string]uint64
|
||||
}
|
||||
|
||||
func newNetwork(user *user, record *Network) *network {
|
||||
@ -235,6 +236,12 @@ func (u *user) run() {
|
||||
})
|
||||
case eventDownstreamDisconnected:
|
||||
dc := e.dc
|
||||
|
||||
for net, rc := range dc.ringConsumers {
|
||||
seq := rc.Close()
|
||||
net.history[dc.clientName] = seq
|
||||
}
|
||||
|
||||
for i := range u.downstreamConns {
|
||||
if u.downstreamConns[i] == dc {
|
||||
u.downstreamConns = append(u.downstreamConns[:i], u.downstreamConns[i+1:]...)
|
||||
|
Loading…
Reference in New Issue
Block a user