提交 e545b202 编写于 作者: V Violeta Georgieva

Make AbstractResponseBodySubscriber.onWritePossible thread-safe

When there are simultaneous invocations of onWritePossible, only the
first one should succeed. This can happens when
AbstractResponseBodySubscriber.onNext and
WriteListener.onWritePossible() are called respectively by the
application and the web container.
上级 e9d8152a
...@@ -152,10 +152,13 @@ abstract class AbstractResponseBodySubscriber implements Subscriber<DataBuffer> ...@@ -152,10 +152,13 @@ abstract class AbstractResponseBodySubscriber implements Subscriber<DataBuffer>
* UNSUBSCRIBED * UNSUBSCRIBED
* | * |
* v * v
* REQUESTED <---> RECEIVED * REQUESTED -------------------> RECEIVED
* | | * ^ ^
* v v * | |
* COMPLETED * --------- WRITING <-----
* |
* v
* COMPLETED
* </pre> * </pre>
* Refer to the individual states for more information. * Refer to the individual states for more information.
*/ */
...@@ -206,36 +209,41 @@ abstract class AbstractResponseBodySubscriber implements Subscriber<DataBuffer> ...@@ -206,36 +209,41 @@ abstract class AbstractResponseBodySubscriber implements Subscriber<DataBuffer>
/** /**
* State that gets entered after a buffer has been * State that gets entered after a buffer has been
* {@linkplain Subscriber#onNext(Object) received}. Responds to * {@linkplain Subscriber#onNext(Object) received}. Responds to
* {@code onWritePossible} by writing the current buffer, and if it can be * {@code onWritePossible} by writing the current buffer and changes
* written completely, changes state to either {@link #REQUESTED} if the * the state to {@link #WRITING}. If it can be written completely,
* subscription has not been completed; or {@link #COMPLETED} if it has. * changes the state to either {@link #REQUESTED} if the subscription
* has not been completed; or {@link #COMPLETED} if it has. If it cannot
* be written completely the state will be changed to {@link #RECEIVED}.
*/ */
RECEIVED { RECEIVED {
@Override @Override
void onWritePossible(AbstractResponseBodySubscriber subscriber) { void onWritePossible(AbstractResponseBodySubscriber subscriber) {
DataBuffer dataBuffer = subscriber.currentBuffer; if (subscriber.changeState(this, WRITING)) {
try { DataBuffer dataBuffer = subscriber.currentBuffer;
boolean writeCompleted = subscriber.write(dataBuffer); try {
if (writeCompleted) { boolean writeCompleted = subscriber.write(dataBuffer);
if (dataBuffer instanceof FlushingDataBuffer) { if (writeCompleted) {
subscriber.flush(); if (dataBuffer instanceof FlushingDataBuffer) {
} subscriber.flush();
subscriber.releaseBuffer(); }
boolean subscriptionCompleted = subscriber.subscriptionCompleted; subscriber.releaseBuffer();
if (!subscriptionCompleted) { boolean subscriptionCompleted = subscriber.subscriptionCompleted;
if (subscriber.changeState(this, REQUESTED)) { if (!subscriptionCompleted) {
subscriber.changeState(WRITING, REQUESTED);
subscriber.subscription.request(1); subscriber.subscription.request(1);
} }
} else {
else { subscriber.changeState(WRITING, COMPLETED);
if (subscriber.changeState(this, COMPLETED)) {
subscriber.close(); subscriber.close();
} }
} }
else {
subscriber.changeState(WRITING, RECEIVED);
}
}
catch (IOException ex) {
subscriber.onError(ex);
} }
}
catch (IOException ex) {
subscriber.onError(ex);
} }
} }
...@@ -244,6 +252,16 @@ abstract class AbstractResponseBodySubscriber implements Subscriber<DataBuffer> ...@@ -244,6 +252,16 @@ abstract class AbstractResponseBodySubscriber implements Subscriber<DataBuffer>
subscriber.subscriptionCompleted = true; subscriber.subscriptionCompleted = true;
} }
}, },
/**
* State that gets entered after a writing of the current buffer has been
* {@code onWritePossible started}.
*/
WRITING {
@Override
void onComplete(AbstractResponseBodySubscriber subscriber) {
subscriber.subscriptionCompleted = true;
}
},
/** /**
* The terminal completed state. Does not respond to any events. * The terminal completed state. Does not respond to any events.
*/ */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册