/*
 * Part of the CCNx Java Library.
 *
 * Copyright (C) 2011 Palo Alto Research Center, Inc.
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version 2.1
 * as published by the Free Software Foundation. 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details. You should have received
 * a copy of the GNU Lesser General Public License along with this library;
 * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301 USA.
 */
package org.ccnx.ccn.impl.support;

public class ConcurrencyUtils {
	
	/**
	 * A generic waiter implemented as an abstract class
	 * 
	 * The generic waiter handles timeouts and deciding whether to continue waiting
	 * on spurious wakeup based on a condition. You can hand it an Object to synchronize on
	 * (syncValue) and an Object to check. Both are handed back to the abstract check method as
	 * the parameters "syncValue" and "checkValue".  The wait ends when either check(syncValue, checkValue)
	 * returns true or the timeout expires.
	 * 
	 * A convenient way to use the waiter is to instantiate the abstract method in an anonymous class.
	 * So for example, if you wanted to wait 500 ms for a static Boolean foo to become true and 
	 * synchronize on an Object named lock you could do it like this, instantiating "check" in the 
	 * anonymous class to check the value of foo.
	 * 
	 * Object lock = new Object();
	 * new Waiter(500) {
	 *		@Override
	 *		protected boolean check(Object syncValue, Object checkValue) throws Exception {
	 *			return (Boolean)checkValue;
	 *		}
	 *	}.wait(lock, foo);
	 * 
	 */
	public static abstract class Waiter {
		protected long timeout;
		protected Waiter(long timeout) {
			this.timeout = timeout;
		}
		public void wait(Object syncValue, Object checkValue) throws Exception {
			synchronized (syncValue) {
				long startTime = System.currentTimeMillis();
				while (!check(syncValue, checkValue) && timeout > 0) {
					syncValue.wait(timeout);
					timeout -= (System.currentTimeMillis() - startTime);
				}
			}
		}
		
		protected abstract boolean check(Object o, Object check) throws Exception;
	}
}

/*
 * Part of the CCNx Java Library.
 *
 * Copyright (C) 2011 Palo Alto Research Center, Inc.
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version 2.1
 * as published by the Free Software Foundation. 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details. You should have received
 * a copy of the GNU Lesser General Public License along with this library;
 * if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301 USA.
 */
package org.ccnx.ccn.impl.support;

public class ConcurrencyUtils {
	
	/**
	 * A generic waiter implemented as an abstract class
	 * 
	 * The generic waiter handles timeouts and deciding whether to continue waiting
	 * on spurious wakeup based on a condition. You can hand it an Object to synchronize on
	 * (syncValue) and an Object to check. Both are handed back to the abstract check method as
	 * the parameters "syncValue" and "checkValue".  The wait ends when either check(syncValue, checkValue)
	 * returns true or the timeout expires.
	 * 
	 * A convenient way to use the waiter is to instantiate the abstract method in an anonymous class.
	 * So for example, if you wanted to wait 500 ms for a static Boolean foo to become true and 
	 * synchronize on an Object named lock you could do it like this, instantiating "check" in the 
	 * anonymous class to check the value of foo.
	 * 
	 * Object lock = new Object();
	 * new Waiter(500) {
	 *		@Override
	 *		protected boolean check(Object syncValue, Object checkValue) throws Exception {
	 *			return (Boolean)checkValue;
	 *		}
	 *	}.wait(lock, foo);
	 */
	public static abstract class Waiter {
		protected long timeout;
		protected Waiter(long timeout) {
			this.timeout = timeout;
		}
		
		/**
		 * Wait until "check" returns true, or timeout is elapsed. Handles spurious wakeups
		 * by calling check in a loop.
		 * 
		 * @param syncValue - wait under this lock, also passed to check routine
		 * @param checkValue - value to pass to check to allow subclass to test condition
		 * @throws Exception
		 */
		public void wait(Object syncValue, Object checkValue) throws Exception {
			synchronized (syncValue) {
				long startTime = System.currentTimeMillis();
				while (!check(syncValue, checkValue) && timeout > 0) {
					syncValue.wait(timeout);
					timeout -= (System.currentTimeMillis() - startTime);
				}
			}
		}
		
		/**
		 * Check to see if condition is met
		 * 
		 * @param syncValue the lock object which could be part of the condition check
		 * @param checkValue value to check for end condition
		 * @return true if condition is met (and we should stop waiting)
		 * @throws Exception
		 */
		protected abstract boolean check(Object syncValue, Object checkValue) throws Exception;
	}
}

Add documention for waiter methods refs #100460