001: // $Id: Promise.java,v 1.10 2005/07/17 11:33:58 chrislott Exp $
002:
003: package org.jgroups.util;
004:
005: import org.jgroups.TimeoutException;
006:
007: /**
008: * Allows a thread to submit an asynchronous request and to wait for the result. The caller may choose to check
009: * for the result at a later time, or immediately and it may block or not. Both the caller and responder have to
010: * know the promise.
011: * @author Bela Ban
012: */
013: public class Promise {
014: Object result = null;
015: boolean hasResult = false;
016:
017: /**
018: * Blocks until a result is available, or timeout milliseconds have elapsed
019: * @param timeout
020: * @return An object
021: * @throws TimeoutException. If a timeout occurred (implies that timeout > 0)
022: */
023: public Object getResultWithTimeout(long timeout)
024: throws TimeoutException {
025: synchronized (this ) {
026: try {
027: return _getResultWithTimeout(timeout);
028: } finally {
029: notifyAll();
030: }
031: }
032: }
033:
034: /**
035: * Blocks until a result is available, or timeout milliseconds have elapsed. Needs to be called with
036: * a lock held on 'this'
037: * @param timeout
038: * @return An object
039: * @throws TimeoutException. If a timeout occurred (implies that timeout > 0)
040: */
041: private Object _getResultWithTimeout(long timeout)
042: throws TimeoutException {
043: Object ret = null;
044: long time_to_wait = timeout, start;
045: boolean timeout_occurred = false;
046:
047: start = System.currentTimeMillis();
048: while (hasResult == false) {
049: if (timeout <= 0) {
050: doWait();
051: } else {
052: if (time_to_wait <= 0) {
053: timeout_occurred = true;
054: break; // terminate the while loop
055: } else {
056: doWait(time_to_wait);
057: time_to_wait = timeout
058: - (System.currentTimeMillis() - start);
059: }
060: }
061: }
062:
063: ret = result;
064: result = null;
065: hasResult = false;
066: if (timeout_occurred)
067: throw new TimeoutException();
068: else
069: return ret;
070: }
071:
072: public Object getResult() {
073: try {
074: return getResultWithTimeout(0);
075: } catch (TimeoutException e) {
076: return null;
077: }
078: }
079:
080: /**
081: * Returns the result, but never throws a TimeoutException; returns null instead.
082: * @param timeout
083: * @return Object
084: */
085: public Object getResult(long timeout) {
086: try {
087: return getResultWithTimeout(timeout);
088: } catch (TimeoutException e) {
089: return null;
090: }
091: }
092:
093: void doWait() {
094: try {
095: wait();
096: } catch (InterruptedException e) {
097: }
098: }
099:
100: void doWait(long timeout) {
101: try {
102: wait(timeout);
103: } catch (InterruptedException e) {
104: }
105: }
106:
107: /**
108: * Checks whether result is available. Does not block.
109: */
110: public boolean hasResult() {
111: synchronized (this ) {
112: return hasResult;
113: }
114: }
115:
116: /**
117: * Sets the result and notifies any threads
118: * waiting for it
119: */
120: public void setResult(Object obj) {
121: synchronized (this ) {
122: result = obj;
123: hasResult = true;
124: notifyAll();
125: }
126: }
127:
128: /**
129: * Causes all waiting threads to return
130: */
131: public void reset() {
132: synchronized (this ) {
133: result = null;
134: hasResult = false;
135: notifyAll();
136: }
137: }
138:
139: public String toString() {
140: return "hasResult=" + hasResult + ",result=" + result;
141: }
142:
143: }
|