blob: a3970141b9d4add7a73ceda5c21893a6821c100d [file] [log] [blame]
/** Notice of modification as required by the LGPL
* This file was modified by Gemstone Systems Inc. on
* $Date$
**/
// $Id: Promise.java,v 1.10 2005/07/17 11:33:58 chrislott Exp $
package com.gemstone.org.jgroups.util;
import com.gemstone.org.jgroups.TimeoutException;
/**
* Allows a thread to submit an asynchronous request and to wait for the result. The caller may choose to check
* for the result at a later time, or immediately and it may block or not. Both the caller and responder have to
* know the promise.
* @author Bela Ban
*/
public class Promise {
Object result=null;
boolean hasResult=false;
/**
* Blocks until a result is available, or timeout milliseconds have elapsed
* @param timeout
* @return An object
* @throws TimeoutException if a timeout occurred (implies that timeout > 0)
*/
public Object getResultWithTimeout(long timeout) throws TimeoutException {
synchronized(this) {
try {
return _getResultWithTimeout(timeout);
}
finally {
notifyAll();
}
}
}
/**
* Blocks until a result is available, or timeout milliseconds have elapsed. Needs to be called with
* a lock held on 'this'
* @param timeout
* @return An object
* @throws TimeoutException if a timeout occurred (implies that timeout > 0)
*/
private Object _getResultWithTimeout(long timeout) throws TimeoutException {
Object ret=null;
long time_to_wait=timeout;
long start;
boolean timeout_occurred=false;
start=System.currentTimeMillis();
while(hasResult == false && !Thread.currentThread().isInterrupted()) {
if(timeout <= 0) {
doWait();
}
else {
if(time_to_wait <= 0) {
timeout_occurred=true;
break; // terminate the while loop
}
else {
doWait(time_to_wait);
time_to_wait=timeout - (System.currentTimeMillis() - start);
}
}
}
ret=result;
result=null;
hasResult=false;
if(timeout_occurred)
throw new TimeoutException();
else
return ret;
}
public Object getResult() {
try {
return getResultWithTimeout(0);
}
catch(TimeoutException e) {
return null;
}
}
/**
* Returns the result, but never throws a TimeoutException; returns null instead.
* @param timeout
* @return Object
*/
public Object getResult(long timeout) {
try {
return getResultWithTimeout(timeout);
}
catch(TimeoutException e) {
return null;
}
}
void doWait() {
try {wait();} catch(InterruptedException e) {
Thread.currentThread().interrupt(); // GemStoneAddition
}
}
void doWait(long timeout) {
// LogWriterI18n log = new PureLogWriter(LogWriterImpl.ALL_LEVEL);
// log.fine("Promise.doWait("+timeout+") invoked");
try {wait(timeout);} catch(InterruptedException e) {
Thread.currentThread().interrupt(); // GemStoneAddition
}
}
/**
* Checks whether result is available. Does not block.
*/
public boolean hasResult() {
synchronized(this) {
return hasResult;
}
}
/**
* Sets the result and notifies any threads
* waiting for it
*/
public void setResult(Object obj) {
synchronized(this) {
result=obj;
hasResult=true;
notifyAll();
}
}
/**
* Causes all waiting threads to return
*/
public void reset() {
synchronized(this) {
result=null;
hasResult=false;
notifyAll();
}
}
@Override // GemStoneAddition
public String toString() {
return "hasResult=" + hasResult + ",result=" + result;
}
}