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,7 +59,7 @@ func (socket *Socket) Close() {
59 59
 	socket.closed = true
60 60
 	socket.Unlock()
61 61
 
62
-	go socket.send()
62
+	socket.wakeWriter()
63 63
 }
64 64
 
65 65
 // CertFP returns the fingerprint of the certificate provided by the client.
@@ -134,10 +134,22 @@ func (socket *Socket) Write(data string) (err error) {
134 134
 	}
135 135
 	socket.Unlock()
136 136
 
137
-	go socket.send()
137
+	socket.wakeWriter()
138 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 153
 // SetFinalData sets the final data to send when the SocketWriter closes.
142 154
 func (socket *Socket) SetFinalData(data string) {
143 155
 	socket.Lock()
@@ -163,19 +175,21 @@ func (socket *Socket) readyToWrite() bool {
163 175
 // send actually writes messages to socket.Conn; it may block
164 176
 func (socket *Socket) send() {
165 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 187
 		select {
167 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 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 193
 			return
180 194
 		}
181 195
 	}

Loading…
Cancel
Save