com.navercorp.pinpoint.rpc.DefaultFuture Maven / Gradle / Ivy
/*
* Copyright 2014 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.navercorp.pinpoint.rpc;
import org.jboss.netty.util.Timeout;
import org.jboss.netty.util.TimerTask;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import java.util.Objects;
/**
* @author emeroad
*/
public class DefaultFuture implements TimerTask, Future {
private static final Logger logger = LogManager.getLogger(DefaultFuture.class);
private final long timeoutMillis;
private int waiters = 0;
private boolean ready = false;
private T result;
private Throwable cause;
private Timeout timeout;
private FailureEventHandler failureEventHandler;
private FutureListener listener;
public DefaultFuture() {
this(3000);
}
public DefaultFuture(long timeoutMillis) {
this.timeoutMillis = timeoutMillis;
}
@Override
public synchronized T getResult() {
if (this.cause != null) {
throw new PinpointSocketException(cause);
}
return result;
}
@Override
public synchronized Throwable getCause() {
return cause;
}
@Override
public synchronized boolean isReady() {
return ready;
}
@Override
public synchronized boolean isSuccess() {
return ready && cause == null;
}
public boolean setResult(T message) {
synchronized (this) {
if (ready) {
return false;
}
this.ready = true;
this.result = message;
if (waiters > 0) {
notifyAll();
}
}
cancelTimeout();
notifyListener();
return true;
}
public boolean setFailure(Throwable cause) {
synchronized (this) {
if (ready) {
return false;
}
this.ready = true;
this.cause = cause;
if (waiters > 0) {
notifyAll();
}
}
cancelTimeout();
notifyFailureHandle();
notifyListener();
return true;
}
private boolean fireTimeout() {
synchronized (this) {
if (ready) {
return false;
}
this.ready = true;
this.cause = new PinpointSocketException("timeout");
if (waiters > 0) {
notifyAll();
}
}
// don't need timeout.cancel because of already being timeout.
notifyFailureHandle();
notifyListener();
return true;
}
private void cancelTimeout() {
final Timeout timeout = this.timeout;
if (timeout != null) {
timeout.cancel();
this.timeout = null;
}
}
private void notifyListener() {
FutureListener listener = this.listener;
if (listener != null) {
fireOnComplete(listener);
this.listener = null;
}
}
protected void notifyFailureHandle() {
FailureEventHandler failureEventHandler = this.failureEventHandler;
if (failureEventHandler != null) {
failureEventHandler.fireFailure();
this.failureEventHandler = null;
}
}
@Override
public boolean setListener(FutureListener listener) {
Objects.requireNonNull(listener, "listener");
boolean alreadyReady = false;
synchronized (this) {
if (ready) {
alreadyReady = true;
} else {
this.listener = listener;
}
}
if (alreadyReady) {
fireOnComplete(listener);
}
return !alreadyReady;
}
private boolean fireOnComplete(FutureListener listener) {
try {
listener.onComplete(this);
return true;
} catch (Throwable th) {
logger.warn("FutureListener.onComplete() fail Caused:{}", th.getMessage(), th);
return false;
}
}
@Override
public boolean await(long timeoutMillis) {
return await0(timeoutMillis);
}
@Override
public boolean await() {
return await0(this.timeoutMillis);
}
private boolean await0(long timeoutMillis) {
if (timeoutMillis < 0) {
throw new IllegalArgumentException("timeoutMillis must not be negative :" + timeoutMillis);
}
boolean interrupted = false;
try {
synchronized (this) {
if (ready) {
return true;
}
try {
this.waiters++;
wait(timeoutMillis);
} catch (InterruptedException e) {
interrupted = true;
} finally {
this.waiters--;
}
return ready;
}
} finally {
if (interrupted) {
Thread.currentThread().interrupt();
}
}
}
@Override
public void run(Timeout timeout) throws Exception {
if (timeout.isCancelled()) {
return;
}
this.fireTimeout();
}
public void setTimeout(Timeout timeout) {
this.timeout = Objects.requireNonNull(timeout, "timeout");
}
public void setFailureEventHandler(FailureEventHandler failureEventHandler) {
this.failureEventHandler = Objects.requireNonNull(failureEventHandler, "failureEventHandler");
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("DefaultFuture");
sb.append("{ready=").append(ready);
sb.append(", result=").append(result);
sb.append(", cause=").append(cause);
sb.append('}');
return sb.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy