|
@@ -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
|
}
|