/*
 *
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You 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 flash.util;

import java.io.Serializable;

/**
 * Subclasses of AbstractCache implement various cache policies.
 * <p>
 * Users of these subclasses should override fetch() or fetchSerial()
 * to provide the logic for retreiving entries that are not in cache.
 * <p>
 * If you override fetchSerial(), only one thread will enter fetch()
 * at the same time.
 */
public abstract class AbstractCache implements Serializable
{
	private static class Lock {}
	private Lock lock = new Lock();
	private Thread busyThread;

	/**
	 * subclasses override fetch() to fetch values that are not in
	 * cache.
	 *
	 * The default implementation uses a semaphore to serialize
	 * access to the fetchSerial method.
	 *
	 * @return the value to cache.  null's are okay.
	 */
	protected Object fetch(Object key)
	{
		synchronized(lock)
		{
			Thread currentThread = Thread.currentThread();
			if (busyThread == currentThread)
			{
				throw new IllegalStateException("AbstractCache.fetch is not re-entrant");
			}

			while (busyThread != null)
			{
				try
				{
					lock.wait();
				}
				catch (InterruptedException e)
				{
				}
			}

			busyThread = currentThread;
		}

		try
		{
			return fetchSerial(key);
		}
		finally
		{
			synchronized (lock)
			{
				busyThread = null;
				lock.notify();
			}
		}
	}

	/**
	 * users can override this hook to add logic for fetching
	 * values that is automatically serialized by the base class.
	 */
	protected Object fetchSerial(Object key)
	{
		return null;
	}

	/**
	 * retreive a value from the cache, invoking fetch() if the value is
	 * not there.  this method is final -- implementations should
	 * override fetch().
	 *
	 * Note: null values can be stored in the cache.  This is useful
	 * for resource caches that fail-fast, when a resource doesn't
	 * exist.  fetch() will return null, and null will be stored in the
	 * cache under the given key, like any other value.
	 */
	public abstract Object get(Object key);

	abstract public void remove(Object key);

	abstract public void put(Object key, Object value);

	abstract public void setSize(int size);

	abstract public void clear();

	// statistics
	long hits;
	long misses;
	long missPenalty;

	static public boolean verbose = false;

	final void report()
	{
		if (verbose)
		{
			double tries = misses+hits;
			double penalty = missPenalty/(double)misses;

			System.out.println(this + " hit rate: " + (hits*100)/tries
							   + " " + hits + "/" + misses
							   + " penalty " + penalty);
		}
	}
}