Browse Source

try to reduce redundant goroutines

tags/v0.12.0
Shivaram Lingamneni 6 years ago
parent
commit
f54561171e
1 changed files with 26 additions and 12 deletions
  1. 26
    12
      irc/socket.go

+ 26
- 12
irc/socket.go View File

59
 	socket.closed = true
59
 	socket.closed = true
60
 	socket.Unlock()
60
 	socket.Unlock()
61
 
61
 
62
-	go socket.send()
62
+	socket.wakeWriter()
63
 }
63
 }
64
 
64
 
65
 // CertFP returns the fingerprint of the certificate provided by the client.
65
 // CertFP returns the fingerprint of the certificate provided by the client.
134
 	}
134
 	}
135
 	socket.Unlock()
135
 	socket.Unlock()
136
 
136
 
137
-	go socket.send()
137
+	socket.wakeWriter()
138
 	return
138
 	return
139
 }
139
 }
140
 
140
 
141
+// wakeWriter starts the goroutine that actually performs the write, without blocking
142
+func (socket *Socket) wakeWriter() {
143
+	// attempt to acquire the trylock
144
+	select {
145
+	case <-socket.writerSlotOpen:
146
+		// acquired the trylock; send() will release it
147
+		go socket.send()
148
+	default:
149
+		// failed to acquire; the holder will check for more data after releasing it
150
+	}
151
+}
152
+
141
 // SetFinalData sets the final data to send when the SocketWriter closes.
153
 // SetFinalData sets the final data to send when the SocketWriter closes.
142
 func (socket *Socket) SetFinalData(data string) {
154
 func (socket *Socket) SetFinalData(data string) {
143
 	socket.Lock()
155
 	socket.Lock()
163
 // send actually writes messages to socket.Conn; it may block
175
 // send actually writes messages to socket.Conn; it may block
164
 func (socket *Socket) send() {
176
 func (socket *Socket) send() {
165
 	for {
177
 	for {
178
+		// we are holding the trylock: actually do the write
179
+		socket.performWrite()
180
+		// surrender the trylock, avoiding a race where a write comes in after we've
181
+		// checked readyToWrite() and it returned false, but while we still hold the trylock:
182
+		socket.writerSlotOpen <- true
183
+		// check if more data came in while we held the trylock:
184
+		if !socket.readyToWrite() {
185
+			return
186
+		}
166
 		select {
187
 		select {
167
 		case <-socket.writerSlotOpen:
188
 		case <-socket.writerSlotOpen:
168
-			// got the trylock: actually do the write
169
-			socket.performWrite()
170
-			// surrender the trylock:
171
-			socket.writerSlotOpen <- true
172
-			// check if more data came in while we held the trylock:
173
-			if !socket.readyToWrite() {
174
-				return
175
-			}
189
+			// got the trylock, loop back around and write
176
 		default:
190
 		default:
177
-			// someone else has the trylock; if there's more data to write,
178
-			// they'll see if after they release it
191
+			// failed to acquire; exit and wait for the holder to observe readyToWrite()
192
+			// after releasing it
179
 			return
193
 			return
180
 		}
194
 		}
181
 	}
195
 	}

Loading…
Cancel
Save