package org.jgroups.util; import org.jgroups.TimeoutException; /** * Class that checks on a condition and - if condition doesn't match the expected result - waits until the result * matches the expected result, or a timeout occurs. First version used WaitableBoolean from util.concurrent, but * that class would not allow for timeouts. * @author Bela Ban * @version $Id: CondVar.java.txt,v 1.1 2006/12/31 14:56:56 belaban Exp $ */ public class CondVar { Object cond; final String name; final Object lock; public CondVar(String name, Object cond) { this.name=name; this.cond=cond; lock=this; } public CondVar(String name, Object cond, Object lock) { this.name=name; this.cond=cond; this.lock=lock; } public Object get() { synchronized(lock) { return cond; } } /** Sets the result */ public void set(Object result) { synchronized(lock) { cond=result; lock.notifyAll(); } } public Object getLock() { return lock; } /** * Waits until the condition matches the expected result. Returns immediately if they match, otherwise waits * for timeout milliseconds or until the results match. * @param result The result, needs to match the condition (using equals()). * @param timeout Number of milliseconds to wait. A value of <= 0 means to wait forever * @throws TimeoutException Thrown if the result still doesn't match the condition after timeout * milliseconds have elapsed */ public void waitUntilWithTimeout(Object result, long timeout) throws TimeoutException { _waitUntilWithTimeout(result, timeout); } /** * Waits until the condition matches the expected result. Returns immediately if they match, otherwise waits * for timeout milliseconds or until the results match. This method doesn't throw a TimeoutException * @param result The result, needs to match the condition (using equals()). * @param timeout Number of milliseconds to wait. A value of <= 0 means to wait forever */ public void waitUntil(Object result, long timeout) { try { _waitUntilWithTimeout(result, timeout); } catch(TimeoutException e) { } } public void waitUntil(Object result) { try {waitUntilWithTimeout(result, 0);} catch(TimeoutException e) {} } private void _waitUntilWithTimeout(Object result, long timeout) throws TimeoutException { long time_to_wait=timeout, start; boolean timeout_occurred=false; synchronized(lock) { if(result == null && cond == null) return; start=System.currentTimeMillis(); while(match(result, cond) == false) { 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); } } } if(timeout_occurred) throw new TimeoutException(); } } void doWait() { try {lock.wait();} catch(InterruptedException e) {} } void doWait(long timeout) { try {lock.wait(timeout);} catch(InterruptedException e) {} } private boolean match(Object o1, Object o2) { if(o1 != null) return o1.equals(o2); else return o2.equals(o1); } public String toString() { return name + "=" + cond; } }