package jane.core.map;
abstract class CacheEntryBase<V>
{
protected long versionCopy;
protected volatile long version;
protected V value;
/**
* Determines the ordering of objects in this priority queue.
* @return <code>true</code> if parameter <tt>a</tt> is less than parameter <tt>b</tt>.
*/
final boolean lessThan(CacheEntryBase<?> that)
{
// reverse the parameter order so that the queue keeps the oldest items
return versionCopy > that.versionCopy;
}
}
/**
* A PriorityQueue maintains a partial ordering of its elements such that the least element can always be found in constant time.
* Put()'s and pop()'s require log(size) time.
*
* <p><b>NOTE</b>: This class will pre-allocate a full array of length <code>maxSize+1</code>.
*/
final class LRUQueue<T extends CacheEntryBase<?>>
{
final T[] heap;
int size; // the number of elements currently stored in the PriorityQueue
int maxSize;
LRUQueue(int maxSize, T[] heap)
{
this.heap = heap;
this.maxSize = maxSize;
}
static int calHeapSize(int maxSize)
{
if(maxSize <= 0)
return 2; // allocate 1 extra to avoid if statement in top()
else if(maxSize == Integer.MAX_VALUE)
throw new IllegalArgumentException("too big maxSize");
return maxSize + 1; // +1 because all access to heap is 1-based. heap[0] is unused.
}
T insertWithOverflow(T element)
{
if(size < maxSize)
{
int i = ++size; // Adds an Object to a PriorityQueue in log(size) time
for(int j = i >>> 1; j > 0 && element.lessThan(heap[j]); i = j, j >>>= 1) // upHeap()
heap[i] = heap[j]; // shift parents down
heap[i] = element; // install saved node
return null;
}
T ret = heap[1];
if(element.lessThan(ret) || size <= 0)
return element;
downHeap(element);
return ret;
}
/** Removes and returns the least element of the PriorityQueue in log(size) time. */
T pop()
{
if(size <= 0)
return null;
T ret = heap[1]; // save first value
if(size == 1)
{
heap[1] = null; // permit GC of objects
size = 0;
return ret;
}
T node = heap[size]; // move last to first
heap[size--] = null; // permit GC of objects
downHeap(node); // adjust heap
return ret;
}
private void downHeap(T node)
{
for(int i = 1, j = 2, k = 3;;) // j = i << 1 (find smaller child); k = j + 1;
{
if(k <= size && heap[k].lessThan(heap[j]))
j = k;
if(j > size || !heap[j].lessThan(node))
{
heap[i] = node; // install saved node
return;
}
heap[i] = heap[j]; // shift up child
i = j;
j = i << 1;
k = j + 1;
}
}
}