Skip to content

Commit f0eaa72

Browse files
committed
prevent locking in buffered data sink
1 parent 1eab1c4 commit f0eaa72

File tree

1 file changed

+27
-40
lines changed

1 file changed

+27
-40
lines changed

AndroidAsync/src/com/koushikdutta/async/BufferedDataSink.java

Lines changed: 27 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
import com.koushikdutta.async.callback.CompletedCallback;
44
import com.koushikdutta.async.callback.WritableCallback;
55

6-
import java.nio.ByteBuffer;
7-
86
public class BufferedDataSink implements DataSink {
97
DataSink mDataSink;
108
public BufferedDataSink(DataSink datasink) {
@@ -14,7 +12,7 @@ public BufferedDataSink(DataSink datasink) {
1412
public boolean isBuffering() {
1513
return mPendingWrites.hasRemaining() || forceBuffering;
1614
}
17-
15+
1816
public DataSink getDataSink() {
1917
return mDataSink;
2018
}
@@ -28,58 +26,50 @@ public void forceBuffering(boolean forceBuffering) {
2826

2927
public void setDataSink(DataSink datasink) {
3028
mDataSink = datasink;
31-
mDataSink.setWriteableCallback(new WritableCallback() {
32-
@Override
33-
public void onWriteable() {
34-
writePending();
35-
}
36-
});
29+
mDataSink.setWriteableCallback(this::writePending);
3730
}
3831

3932
private void writePending() {
4033
if (forceBuffering)
4134
return;
4235

4336
// Log.i("NIO", "Writing to buffer...");
44-
if (mPendingWrites.hasRemaining()) {
37+
boolean empty;
38+
synchronized (mPendingWrites) {
4539
mDataSink.write(mPendingWrites);
46-
if (mPendingWrites.remaining() == 0) {
47-
if (endPending)
48-
mDataSink.end();
49-
}
40+
empty = mPendingWrites.isEmpty();
41+
}
42+
if (empty) {
43+
if (endPending)
44+
mDataSink.end();
5045
}
51-
if (!mPendingWrites.hasRemaining() && mWritable != null)
46+
if (empty && mWritable != null)
5247
mWritable.onWriteable();
5348
}
5449

55-
ByteBufferList mPendingWrites = new ByteBufferList();
50+
final ByteBufferList mPendingWrites = new ByteBufferList();
5651

5752
@Override
5853
public void write(ByteBufferList bb) {
5954
write(bb, false);
6055
}
61-
56+
6257
protected void write(final ByteBufferList bb, final boolean ignoreBuffer) {
6358
if (getServer().getAffinity() != Thread.currentThread()) {
64-
getServer().run(new Runnable() {
65-
@Override
66-
public void run() {
67-
write(bb, ignoreBuffer);
68-
}
69-
});
59+
synchronized (mPendingWrites) {
60+
if (mPendingWrites.remaining() >= mMaxBuffer && !ignoreBuffer)
61+
return;
62+
bb.get(mPendingWrites);
63+
}
64+
getServer().post(this::writePending);
7065
return;
7166
}
7267

7368
if (!isBuffering())
7469
mDataSink.write(bb);
7570

76-
if (bb.remaining() > 0) {
77-
int toRead = Math.min(bb.remaining(), mMaxBuffer);
78-
if (ignoreBuffer)
79-
toRead = bb.remaining();
80-
if (toRead > 0) {
81-
bb.get(mPendingWrites, toRead);
82-
}
71+
synchronized (mPendingWrites) {
72+
bb.get(mPendingWrites);
8373
}
8474
}
8575

@@ -102,7 +92,7 @@ public int remaining() {
10292
public int getMaxBuffer() {
10393
return mMaxBuffer;
10494
}
105-
95+
10696
public void setMaxBuffer(int maxBuffer) {
10797
assert maxBuffer >= 0;
10898
mMaxBuffer = maxBuffer;
@@ -117,18 +107,15 @@ public boolean isOpen() {
117107
@Override
118108
public void end() {
119109
if (getServer().getAffinity() != Thread.currentThread()) {
120-
getServer().run(new Runnable() {
121-
@Override
122-
public void run() {
123-
end();
124-
}
125-
});
110+
getServer().post(this::end);
126111
return;
127112
}
128113

129-
if (mPendingWrites.hasRemaining()) {
130-
endPending = true;
131-
return;
114+
synchronized (mPendingWrites) {
115+
if (mPendingWrites.hasRemaining()) {
116+
endPending = true;
117+
return;
118+
}
132119
}
133120
mDataSink.end();
134121
}

0 commit comments

Comments
 (0)