Skip to content

Commit 6663f06

Browse files
authored
The WebSocketWriter is single-threaded. (square#3571)
We were synchronizing to permit multiple writer threads. But that was a carry-over from the previous design where we supported multiple writer threads. With the current implementation only one thread writes at a time. This synchronization was not necessary.
1 parent a95ec06 commit 6663f06

File tree

2 files changed

+14
-33
lines changed

2 files changed

+14
-33
lines changed

okhttp/src/main/java/okhttp3/internal/ws/WebSocketReader.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@
4646

4747
/**
4848
* An <a href="http://tools.ietf.org/html/rfc6455">RFC 6455</a>-compatible WebSocket frame reader.
49-
* <p>
50-
* This class is not thread safe.
49+
*
50+
* <p>This class is not thread safe.
5151
*/
5252
final class WebSocketReader {
5353
public interface FrameCallback {

okhttp/src/main/java/okhttp3/internal/ws/WebSocketWriter.java

Lines changed: 12 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,7 @@
3939
/**
4040
* An <a href="http://tools.ietf.org/html/rfc6455">RFC 6455</a>-compatible WebSocket frame writer.
4141
*
42-
* <p>This class is partially thread safe. Only a single "main" thread should be sending messages
43-
* via calls to {@link #newMessageSink}, {@link #writePing}, or {@link #writeClose}. Other threads
44-
* may call {@link #writePing}, {@link #writePong}, or {@link #writeClose} which will interleave on
45-
* the wire with frames from the "main" sending thread.
42+
* <p>This class is not thread safe.
4643
*/
4744
final class WebSocketWriter {
4845
final boolean isClient;
@@ -75,16 +72,12 @@ final class WebSocketWriter {
7572

7673
/** Send a ping with the supplied {@code payload}. */
7774
void writePing(ByteString payload) throws IOException {
78-
synchronized (this) {
79-
writeControlFrameSynchronized(OPCODE_CONTROL_PING, payload);
80-
}
75+
writeControlFrame(OPCODE_CONTROL_PING, payload);
8176
}
8277

8378
/** Send a pong with the supplied {@code payload}. */
8479
void writePong(ByteString payload) throws IOException {
85-
synchronized (this) {
86-
writeControlFrameSynchronized(OPCODE_CONTROL_PONG, payload);
87-
}
80+
writeControlFrame(OPCODE_CONTROL_PONG, payload);
8881
}
8982

9083
/**
@@ -108,18 +101,14 @@ void writeClose(int code, ByteString reason) throws IOException {
108101
payload = buffer.readByteString();
109102
}
110103

111-
synchronized (this) {
112-
try {
113-
writeControlFrameSynchronized(OPCODE_CONTROL_CLOSE, payload);
114-
} finally {
115-
writerClosed = true;
116-
}
104+
try {
105+
writeControlFrame(OPCODE_CONTROL_CLOSE, payload);
106+
} finally {
107+
writerClosed = true;
117108
}
118109
}
119110

120-
private void writeControlFrameSynchronized(int opcode, ByteString payload) throws IOException {
121-
assert Thread.holdsLock(this);
122-
111+
private void writeControlFrame(int opcode, ByteString payload) throws IOException {
123112
if (writerClosed) throw new IOException("closed");
124113

125114
int length = payload.size();
@@ -169,10 +158,8 @@ Sink newMessageSink(int formatOpcode, long contentLength) {
169158
return frameSink;
170159
}
171160

172-
void writeMessageFrameSynchronized(int formatOpcode, long byteCount, boolean isFirstFrame,
161+
void writeMessageFrame(int formatOpcode, long byteCount, boolean isFirstFrame,
173162
boolean isFinal) throws IOException {
174-
assert Thread.holdsLock(this);
175-
176163
if (writerClosed) throw new IOException("closed");
177164

178165
int b0 = isFirstFrame ? formatOpcode : OPCODE_CONTINUATION;
@@ -235,19 +222,15 @@ final class FrameSink implements Sink {
235222

236223
long emitCount = buffer.completeSegmentByteCount();
237224
if (emitCount > 0 && !deferWrite) {
238-
synchronized (WebSocketWriter.this) {
239-
writeMessageFrameSynchronized(formatOpcode, emitCount, isFirstFrame, false /* final */);
240-
}
225+
writeMessageFrame(formatOpcode, emitCount, isFirstFrame, false /* final */);
241226
isFirstFrame = false;
242227
}
243228
}
244229

245230
@Override public void flush() throws IOException {
246231
if (closed) throw new IOException("closed");
247232

248-
synchronized (WebSocketWriter.this) {
249-
writeMessageFrameSynchronized(formatOpcode, buffer.size(), isFirstFrame, false /* final */);
250-
}
233+
writeMessageFrame(formatOpcode, buffer.size(), isFirstFrame, false /* final */);
251234
isFirstFrame = false;
252235
}
253236

@@ -259,9 +242,7 @@ final class FrameSink implements Sink {
259242
@Override public void close() throws IOException {
260243
if (closed) throw new IOException("closed");
261244

262-
synchronized (WebSocketWriter.this) {
263-
writeMessageFrameSynchronized(formatOpcode, buffer.size(), isFirstFrame, true /* final */);
264-
}
245+
writeMessageFrame(formatOpcode, buffer.size(), isFirstFrame, true /* final */);
265246
closed = true;
266247
activeWriter = false;
267248
}

0 commit comments

Comments
 (0)