解决setcallback 时可能出现的并发问题 DUBBO-750

git-svn-id: http://code.alibabatech.com/svn/dubbo/trunk@43 1a56cb94-b969-4eaa-88fa-be21384802f2
This commit is contained in:
chao.liuc 2011-10-25 08:09:32 +00:00
parent 3f34281f80
commit 6ffe440029
1 changed files with 39 additions and 22 deletions

View File

@ -38,7 +38,8 @@ import com.alibaba.dubbo.remoting.exchange.Response;
/**
* DefaultFuture.
*
* @author qian.lei
* @author qian.lei
* @author chao.liuc
*/
public class DefaultFuture implements ResponseFuture {
@ -110,8 +111,9 @@ public class DefaultFuture implements ResponseFuture {
}
public void cancel(){
response = new Response(id);
response.setErrorMessage("request future has been canceled.");
Response errorResult = new Response(id);
errorResult.setErrorMessage("request future has been canceled.");
response = errorResult ;
FUTURES.remove(id);
CHANNELS.remove(id);
}
@ -120,16 +122,39 @@ public class DefaultFuture implements ResponseFuture {
return response != null;
}
public void setCallback(ResponseCallback callback) {
if (isDone()) {
try {
callback.done(returnFromResponse());
} catch (Throwable e) {
callback.caught(e);
}
} else {
this.callback = callback;
public void setCallback(ResponseCallback callback) {
if (isDone()) {
invokeCallback(callback);
} else {
boolean isdone = false;
lock.lock();
try{
if (!isDone()) {
this.callback = callback;
} else {
isdone = true;
}
}finally {
lock.unlock();
}
if (isdone){
invokeCallback(callback);
}
}
}
private void invokeCallback(ResponseCallback c){
if (c == null){
throw new NullPointerException("callback cannot be null.");
}
ResponseCallback callbackCopy = c;
c = null;
Object result = null;
try {
result = returnFromResponse();
} catch (Throwable e) {
callbackCopy.caught(e);
}
callbackCopy.done(result);
}
private long getId() {
@ -198,14 +223,8 @@ public class DefaultFuture implements ResponseFuture {
} finally {
lock.unlock();
}
ResponseCallback c = callback;
if (c != null) {
try {
c.done(returnFromResponse());
} catch (Throwable e) {
c.caught(e);
}
callback = null;
if (callback != null) {
invokeCallback(callback);
}
}
@ -217,8 +236,6 @@ public class DefaultFuture implements ResponseFuture {
if (res.getStatus() == Response.CLIENT_TIMEOUT || res.getStatus() == Response.SERVER_TIMEOUT) {
throw new TimeoutException(res.getStatus() == Response.SERVER_TIMEOUT, channel, res.getErrorMessage());
}
FUTURES.remove(id);
CHANNELS.remove(id);
throw new RemotingException(channel, res.getErrorMessage());
}