3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-11-10 22:19:31 +01:00

try to reduce redundant goroutines

This commit is contained in:
Shivaram Lingamneni 2018-04-15 19:05:22 -04:00
parent 4778e7bcc7
commit f54561171e

View File

@ -59,7 +59,7 @@ func (socket *Socket) Close() {
socket.closed = true
socket.Unlock()
go socket.send()
socket.wakeWriter()
}
// CertFP returns the fingerprint of the certificate provided by the client.
@ -134,10 +134,22 @@ func (socket *Socket) Write(data string) (err error) {
}
socket.Unlock()
go socket.send()
socket.wakeWriter()
return
}
// wakeWriter starts the goroutine that actually performs the write, without blocking
func (socket *Socket) wakeWriter() {
// attempt to acquire the trylock
select {
case <-socket.writerSlotOpen:
// acquired the trylock; send() will release it
go socket.send()
default:
// failed to acquire; the holder will check for more data after releasing it
}
}
// SetFinalData sets the final data to send when the SocketWriter closes.
func (socket *Socket) SetFinalData(data string) {
socket.Lock()
@ -163,19 +175,21 @@ func (socket *Socket) readyToWrite() bool {
// send actually writes messages to socket.Conn; it may block
func (socket *Socket) send() {
for {
// we are holding the trylock: actually do the write
socket.performWrite()
// surrender the trylock, avoiding a race where a write comes in after we've
// checked readyToWrite() and it returned false, but while we still hold the trylock:
socket.writerSlotOpen <- true
// check if more data came in while we held the trylock:
if !socket.readyToWrite() {
return
}
select {
case <-socket.writerSlotOpen:
// got the trylock: actually do the write
socket.performWrite()
// surrender the trylock:
socket.writerSlotOpen <- true
// check if more data came in while we held the trylock:
if !socket.readyToWrite() {
return
}
// got the trylock, loop back around and write
default:
// someone else has the trylock; if there's more data to write,
// they'll see if after they release it
// failed to acquire; exit and wait for the holder to observe readyToWrite()
// after releasing it
return
}
}