tail = sentinel.prev;
sentinel.prev = this;
tail.next = this;
prev = tail;
} finally {
lock.unlock();
}
}
/**
* Removes the node from the list.
*
* If the node has not yet been appended to the tail it will wait for that
* operation to complete.
*/
public void remove() {
for (;;) {
if (isUnlinked()) {
continue; // await appendToTail()
}
lock.lock();
try {
if (isUnlinked()) {
continue; // await appendToTail()
}
prev.next = next;
next.prev = prev;
next = UNLINKED; // mark as unlinked
} finally {
lock.unlock();
}
return;
}
}
/**
* Moves the node to the tail.
*
* If the node has been unlinked or is already at the tail, no-ops.
*/
public void moveToTail() {
if (isTail() || isUnlinked()) {
return;
}
lock.lock();
try {
if (isTail() || isUnlinked()) {
return;
}
// unlink
prev.next = next;
next.prev = prev;
// link
next = sentinel; // ordered for isTail()
prev = sentinel.prev;
sentinel.prev = this;
prev.next = this;
} finally {
lock.unlock();
}
}
/**
* Checks whether the node is linked on the list chain.
*
* @return Whether the node has not yet been linked on the list.
*/
public boolean isUnlinked() {
return (next == UNLINKED);
}
/**
* Checks whether the node is the last linked on the list chain.
*
* @return Whether the node is at the tail of the list.
*/
public boolean isTail() {
return (next == sentinel);
}
/*
* Key operators
*/
public K getKey() {
return key;
}
/*
* Value operators
*/
public V getValue() {
return (V) valueUpdater.get(this);
}
public V getAndSetValue(V value) {
return (V) valueUpdater.getAndSet(this, value);
}
public boolean casValue(V expect, V update) {
return valueUpdater.compareAndSet(this, expect, update);
}
/*
* Previous node operators
*/
public Node getPrev() {
return prev;
}
/*
* Next node operators
*/
public Node getNext() {
return next;
}
/*
* Access frequency operators
*/
public boolean isMarked() {
return marked;
}
public void setMarked(boolean marked) {
this.marked = marked;
}
/**
* Only ensures that the values are equal, as the key may be null
* for look-ups.
*/
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
} else if (!(obj instanceof Node)) {
return false;
}
V value = getValue();
Node, ?> node = (Node, ?>) obj;
return (value == null) ? (node.getValue() == null) : value.equals(node.getValue());
}
@Override
public int hashCode() {
return ((key == null) ? 0 : key.hashCode()) ^ ((value == null) ? 0 : value.hashCode());
}
}
/**
* Allows {@link #equals(Object)} to compare using object identity.
*/
private static final class Identity {
private final Object delegate;
public Identity(Object delegate) {
this.delegate = delegate;
}
@Override
public boolean equals(Object o) {
return (o == delegate);
}
}
/**
* An adapter to safely externalize the keys.
*/
private final class KeySet extends AbstractSet {
private final ProductionMap map = ProductionMap.this;
@Override
public int size() {
return map.size();
}
@Override
public void clear() {
map.clear();
}
@Override
public Iterator iterator() {
return new KeyIterator();
}
@Override
public boolean contains(Object obj) {
return map.containsKey(obj);
}
@Override
public boolean remove(Object obj) {
return (map.remove(obj) != null);
}
@Override
public Object[] toArray() {
return map.data.keySet().toArray();
}
@Override
public T[] toArray(T[] array) {
return map.data.keySet().toArray(array);
}
}
/**
* An adapter to safely externalize the keys.
*/
private final class KeyIterator implements Iterator {
private final EntryIterator iterator =
new EntryIterator(ProductionMap.this.data.values().iterator());
public boolean hasNext() {
return iterator.hasNext();
}
public K next() {
return iterator.next().getKey();
}
public void remove() {
iterator.remove();
}
}
/**
* An adapter to represent the data store's values in the external type.
*/
private final class Values extends AbstractCollection {
private final ProductionMap map = ProductionMap.this;
@Override
public int size() {
return map.size();
}
@Override
public void clear() {
map.clear();
}
@Override
public Iterator iterator() {
return new ValueIterator();
}
@Override
public boolean contains(Object o) {
return map.containsValue(o);
}
@Override
public Object[] toArray() {
Collection values = new ArrayList(size());
for (V value : this) {
values.add(value);
}
return values.toArray();
}
@Override
public T[] toArray(T[] array) {
Collection values = new ArrayList(size());
for (V value : this) {
values.add(value);
}
return values.toArray(array);
}
}
/**
* An adapter to represent the data store's values in the external type.
*/
private final class ValueIterator implements Iterator {
private final EntryIterator iterator =
new EntryIterator(ProductionMap.this.data.values().iterator());
public boolean hasNext() {
return iterator.hasNext();
}
public V next() {
return iterator.next().getValue();
}
public void remove() {
iterator.remove();
}
}
/**
* An adapter to represent the data store's entry set in the external type.
*/
private final class EntrySet extends AbstractSet> {
private final ProductionMap map = ProductionMap.this;
@Override
public int size() {
return map.size();
}
@Override
public void clear() {
map.clear();
}
@Override
public Iterator> iterator() {
return new EntryIterator(map.data.values().iterator());
}
@Override
public boolean contains(Object obj) {
if (!(obj instanceof Entry)) {
return false;
}
Entry, ?> entry = (Entry, ?>) obj;
Node node = map.data.get(entry.getKey());
return (node != null) && (node.value.equals(entry.getValue()));
}
@Override
public boolean add(Entry entry) {
return (map.putIfAbsent(entry.getKey(), entry.getValue()) == null);
}
@Override
public boolean remove(Object obj) {
if (!(obj instanceof Entry)) {
return false;
}
Entry, ?> entry = (Entry, ?>) obj;
return map.remove(entry.getKey(), entry.getValue());
}
@Override
public Object[] toArray() {
Collection> entries = new ArrayList>(size());
for (Entry entry : this) {
entries.add(new SimpleEntry(entry));
}
return entries.toArray();
}
@Override
public T[] toArray(T[] array) {
Collection> entries = new ArrayList>(size());
for (Entry entry : this) {
entries.add(new SimpleEntry(entry));
}
return entries.toArray(array);
}
}
/**
* An adapter to represent the data store's entry iterator in the external
* type.
*/
private final class EntryIterator implements Iterator> {
private final Iterator> iterator;
private Entry current;
public EntryIterator(Iterator> iterator) {
this.iterator = iterator;
}
public boolean hasNext() {
return iterator.hasNext();
}
public Entry next() {
current = new NodeEntry(iterator.next());
return current;
}
public void remove() {
if (current == null) {
throw new IllegalStateException();
}
ProductionMap.this.remove(current.getKey(), current.getValue());
current = null;
}
}
/**
* An entry that is tied to the map instance to allow updates through the
* entry or the map to be visible.
*/
private final class NodeEntry implements Entry {
private final ProductionMap map = ProductionMap.this;
private final Node node;
public NodeEntry(Node node) {
this.node = node;
}
public K getKey() {
return node.getKey();
}
public V getValue() {
if (node.isUnlinked()) {
V value = map.get(getKey());
if (value != null) {
return value;
}
}
return node.getValue();
}
public V setValue(V value) {
return map.replace(getKey(), value);
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
} else if (!(obj instanceof Entry)) {
return false;
}
Entry, ?> entry = (Entry, ?>) obj;
return eq(getKey(), entry.getKey()) && eq(getValue(), entry.getValue());
}
@Override
public int hashCode() {
K key = getKey();
V value = getValue();
return ((key == null) ? 0 : key.hashCode()) ^ ((value == null) ? 0 : value.hashCode());
}
@Override
public String toString() {
return getKey() + "=" + getValue();
}
private boolean eq(Object o1, Object o2) {
return (o1 == null) ? (o2 == null) : o1.equals(o2);
}
}
/**
* This duplicates {@link java.util.AbstractMap.SimpleEntry} until the class
* is made accessible (public in JDK-6).
*/
private static class SimpleEntry implements Entry {
private final K key;
private V value;
public SimpleEntry(K key, V value) {
this.key = key;
this.value = value;
}
public SimpleEntry(Entry e) {
this.key = e.getKey();
this.value = e.getValue();
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
public V setValue(V value) {
V oldValue = this.value;
this.value = value;
return oldValue;
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
} else if (!(obj instanceof Entry)) {
return false;
}
Entry, ?> entry = (Entry, ?>) obj;
return eq(key, entry.getKey()) && eq(value, entry.getValue());
}
@Override
public int hashCode() {
return ((key == null) ? 0 : key.hashCode()) ^ ((value == null) ? 0 : value.hashCode());
}
@Override
public String toString() {
return key + "=" + value;
}
private static boolean eq(Object o1, Object o2) {
return (o1 == null) ? (o2 == null) : o1.equals(o2);
}
}
}
././@LongLink 0000000 0000000 0000000 00000000227 00000000000 011566 L ustar root root libconcurrentlinkedhashmap-java-1.1~jdk5.orig/unittest/src/java/com/googlecode/concurrentlinkedhashmap/caches/SynchronizedForwardingConcurrentMap.java libconcurrentlinkedhashmap-java-1.1~jdk5.orig/unittest/src/java/com/googlecode/concurrentlinkedhashm0000600 0000000 0000000 00000005275 11464441225 031272 0 ustar package com.googlecode.concurrentlinkedhashmap.caches;
import static com.google.common.collect.Sets.newLinkedHashSet;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
/**
* A forwarding {@link ConcurrentMap} that wraps each call with a mutex.
*
* @author ben.manes@gmail.com (Ben Manes)
*/
final class SynchronizedForwardingConcurrentMap implements ConcurrentMap {
private final ConcurrentMap delegate;
private final Object lock;
public SynchronizedForwardingConcurrentMap(ConcurrentMap delegate) {
this.delegate = delegate;
this.lock = new Object();
}
public boolean isEmpty() {
synchronized (lock) {
return delegate.isEmpty();
}
}
public int size() {
synchronized (lock) {
return delegate.size();
}
}
public void clear() {
synchronized (lock) {
delegate.clear();
}
}
public boolean containsKey(Object key) {
synchronized (lock) {
return delegate.containsKey(key);
}
}
public boolean containsValue(Object value) {
synchronized (lock) {
return delegate.containsValue(value);
}
}
public V get(Object key) {
synchronized (lock) {
return delegate.get(key);
}
}
public V put(K key, V value) {
synchronized (lock) {
return delegate.put(key, value);
}
}
public V putIfAbsent(K key, V value) {
synchronized (lock) {
return delegate.putIfAbsent(key, value);
}
}
public void putAll(Map extends K, ? extends V> map) {
synchronized (lock) {
delegate.putAll(map);
}
}
public V remove(Object key) {
synchronized (lock) {
return delegate.remove(key);
}
}
public boolean remove(Object key, Object value) {
synchronized (lock) {
return delegate.remove(key, value);
}
}
public boolean replace(K key, V oldValue, V newValue) {
synchronized (lock) {
return delegate.replace(key, oldValue, newValue);
}
}
public V replace(K key, V value) {
synchronized (lock) {
return delegate.replace(key, value);
}
}
public Set keySet() {
synchronized (lock) {
return newLinkedHashSet(delegate.keySet());
}
}
public Collection values() {
synchronized (lock) {
return newLinkedHashSet(delegate.values());
}
}
public Set> entrySet() {
synchronized (lock) {
return newLinkedHashSet(delegate.entrySet());
}
}
@Override
public boolean equals(Object object) {
synchronized (lock) {
return delegate.equals(object);
}
}
@Override
public int hashCode() {
synchronized (lock) {
return delegate.hashCode();
}
}
}
././@LongLink 0000000 0000000 0000000 00000000217 00000000000 011565 L ustar root root libconcurrentlinkedhashmap-java-1.1~jdk5.orig/unittest/src/java/com/googlecode/concurrentlinkedhashmap/caches/LockForwardingConcurrentMap.java libconcurrentlinkedhashmap-java-1.1~jdk5.orig/unittest/src/java/com/googlecode/concurrentlinkedhashm0000600 0000000 0000000 00000007201 11464441225 031261 0 ustar package com.googlecode.concurrentlinkedhashmap.caches;
import static com.google.common.collect.Sets.newLinkedHashSet;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.Lock;
/**
* A forwarding {@link ConcurrentMap} that wraps each call with a lock.
*
* @author ben.manes@gmail.com (Ben Manes)
*/
final class LockForwardingConcurrentMap implements ConcurrentMap {
private final ConcurrentMap delegate;
private final Lock writeLock;
private final Lock readLock;
public LockForwardingConcurrentMap(Lock readLock, Lock writeLock, ConcurrentMap delegate) {
this.writeLock = writeLock;
this.readLock = readLock;
this.delegate = delegate;
}
public boolean isEmpty() {
readLock.lock();
try {
return delegate.isEmpty();
} finally {
readLock.unlock();
}
}
public int size() {
readLock.lock();
try {
return delegate.size();
} finally {
readLock.unlock();
}
}
public void clear() {
writeLock.lock();
try {
delegate.clear();
} finally {
writeLock.unlock();
}
}
public boolean containsKey(Object key) {
readLock.lock();
try {
return delegate.containsKey(key);
} finally {
readLock.unlock();
}
}
public boolean containsValue(Object value) {
readLock.lock();
try {
return delegate.containsValue(value);
} finally {
readLock.unlock();
}
}
public V get(Object key) {
readLock.lock();
try {
return delegate.get(key);
} finally {
readLock.unlock();
}
}
public V put(K key, V value) {
writeLock.lock();
try {
return delegate.put(key, value);
} finally {
writeLock.unlock();
}
}
public V putIfAbsent(K key, V value) {
writeLock.lock();
try {
return delegate.putIfAbsent(key, value);
} finally {
writeLock.unlock();
}
}
public void putAll(Map extends K, ? extends V> map) {
writeLock.lock();
try {
delegate.putAll(map);
} finally {
writeLock.unlock();
}
}
public V remove(Object key) {
writeLock.lock();
try {
return delegate.remove(key);
} finally {
writeLock.unlock();
}
}
public boolean remove(Object key, Object value) {
writeLock.lock();
try {
return delegate.remove(key, value);
} finally {
writeLock.unlock();
}
}
public boolean replace(K key, V oldValue, V newValue) {
writeLock.lock();
try {
return delegate.replace(key, oldValue, newValue);
} finally {
writeLock.unlock();
}
}
public V replace(K key, V value) {
writeLock.lock();
try {
return delegate.replace(key, value);
} finally {
writeLock.unlock();
}
}
public Set keySet() {
readLock.lock();
try {
return newLinkedHashSet(delegate.keySet());
} finally {
readLock.unlock();
}
}
public Collection values() {
readLock.lock();
try {
return newLinkedHashSet(delegate.values());
} finally {
readLock.unlock();
}
}
public Set> entrySet() {
readLock.lock();
try {
return newLinkedHashSet(delegate.entrySet());
} finally {
readLock.unlock();
}
}
@Override
public boolean equals(Object object) {
readLock.lock();
try {
return delegate.equals(object);
} finally {
readLock.unlock();
}
}
@Override
public int hashCode() {
readLock.lock();
try {
return delegate.hashCode();
} finally {
readLock.unlock();
}
}
}
././@LongLink 0000000 0000000 0000000 00000000171 00000000000 011564 L ustar root root libconcurrentlinkedhashmap-java-1.1~jdk5.orig/unittest/src/java/com/googlecode/concurrentlinkedhashmap/caches/Cache.java libconcurrentlinkedhashmap-java-1.1~jdk5.orig/unittest/src/java/com/googlecode/concurrentlinkedhashm0000600 0000000 0000000 00000010437 11414746664 031300 0 ustar package com.googlecode.concurrentlinkedhashmap.caches;
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap.Builder;
import com.googlecode.concurrentlinkedhashmap.caches.BoundedLinkedHashMap.AccessOrder;
import com.googlecode.concurrentlinkedhashmap.caches.ProductionMap.EvictionPolicy;
import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* A collection of cache data structures that can be built.
*
* @author ben.manes@gmail.com (Ben Manes)
*/
public enum Cache {
/** A concurrent linked hash map. */
ConcurrentLinkedHashMap() {
@Override public ConcurrentMap create(CacheBuilder builder) {
return new Builder()
.initialCapacity(builder.initialCapacity)
.concurrencyLevel(builder.concurrencyLevel)
.maximumWeightedCapacity(builder.maximumCapacity)
.build();
}
},
/** A concurrent map using a first-in, first-out eviction policy. */
Concurrent_Fifo() {
@Override public ConcurrentMap create(CacheBuilder builder) {
return new ProductionMap(EvictionPolicy.FIFO, builder);
}
},
/**
* A concurrent map using a second chance first-in, first-out eviction policy.
*/
Concurrent_SecondChanceFifo() {
@Override public ConcurrentMap create(CacheBuilder builder) {
return new ProductionMap(EvictionPolicy.SECOND_CHANCE, builder);
}
},
/** A concurrent map using an eager lock-based LRU eviction policy. */
Concurrent_Lru() {
@Override public ConcurrentMap create(CacheBuilder builder) {
return new ProductionMap(EvictionPolicy.LRU, builder);
}
},
/** LinkedHashMap in FIFO eviction, guarded by read/write lock. */
LinkedHashMap_Fifo_Lock() {
@Override public ConcurrentMap create(CacheBuilder builder) {
ReadWriteLock lock = new ReentrantReadWriteLock();
ConcurrentMap delegate = new BoundedLinkedHashMap(AccessOrder.FIFO, builder);
return new LockForwardingConcurrentMap(lock.readLock(), lock.writeLock(), delegate);
}
},
/** LinkedHashMap in LRU eviction, guarded by lock. */
LinkedHashMap_Lru_Lock() {
@Override public ConcurrentMap create(CacheBuilder builder) {
Lock lock = new ReentrantLock(); // LRU mutates on reads to update access order
ConcurrentMap delegate = new BoundedLinkedHashMap(AccessOrder.LRU, builder);
return new LockForwardingConcurrentMap(lock, lock, delegate);
}
},
/** LinkedHashMap in FIFO eviction, guarded by synchronized monitor. */
LinkedHashMap_Fifo_Sync() {
@Override public ConcurrentMap create(CacheBuilder builder) {
ConcurrentMap delegate = new BoundedLinkedHashMap(AccessOrder.FIFO, builder);
return new SynchronizedForwardingConcurrentMap(delegate);
}
},
/** LinkedHashMap in LRU eviction, guarded by synchronized monitor. */
LinkedHashMap_Lru_Sync() {
@Override public ConcurrentMap create(CacheBuilder builder) {
ConcurrentMap delegate = new BoundedLinkedHashMap(AccessOrder.LRU, builder);
return new SynchronizedForwardingConcurrentMap(delegate);
}
},
/** ConcurrentMap with no eviction policy (unbounded). */
ConcurrentHashMap() {
@Override public ConcurrentMap create(CacheBuilder builder) {
return new ConcurrentHashMap(builder.maximumCapacity, 0.75f, builder.concurrencyLevel);
}
},
/** Ehcache, using FIFO eviction. */
Ehcache_Fifo() {
@Override public ConcurrentMap create(CacheBuilder builder) {
return new EhcacheMap(MemoryStoreEvictionPolicy.FIFO, builder);
}
},
/** Ehcache, using LRU eviction. */
Ehcache_Lru() {
@Override public ConcurrentMap create(CacheBuilder builder) {
return new EhcacheMap(MemoryStoreEvictionPolicy.LRU, builder);
}
};
/** Creates the cache instance. */
abstract ConcurrentMap create(CacheBuilder builder);
}
././@LongLink 0000000 0000000 0000000 00000000200 00000000000 011555 L ustar root root libconcurrentlinkedhashmap-java-1.1~jdk5.orig/unittest/src/java/com/googlecode/concurrentlinkedhashmap/caches/CacheBuilder.java libconcurrentlinkedhashmap-java-1.1~jdk5.orig/unittest/src/java/com/googlecode/concurrentlinkedhashm0000600 0000000 0000000 00000005075 11414746664 031302 0 ustar package com.googlecode.concurrentlinkedhashmap.caches;
import java.util.concurrent.ConcurrentMap;
/**
* A builder that creates bounded map instances. It provides a flexible approach
* for constructing different cache data structures with a named parameter
* syntax.
*
* @author ben.manes@gmail.com (Ben Manes)
*/
public class CacheBuilder {
static final int DEFAULT_CONCURRENCY_LEVEL = 16;
int concurrencyLevel;
int initialCapacity;
int maximumCapacity;
public CacheBuilder() {
maximumCapacity = -1;
concurrencyLevel = DEFAULT_CONCURRENCY_LEVEL;
}
/**
* Specifies the initial capacity of the hash table (default 16).
* This is the number of key-value pairs that the hash table can hold
* before a resize operation is required.
*
* @param initialCapacity the initial capacity used to size the hash table
* to accommodate this many entries.
* @throws IllegalArgumentException if the initialCapacity is negative
*/
public CacheBuilder initialCapacity(int initialCapacity) {
if (initialCapacity < 0) {
throw new IllegalArgumentException();
}
this.initialCapacity = initialCapacity;
return this;
}
/**
* Specifies the maximum capacity to coerces the map to and may exceed it
* temporarily.
*
* @param maximumCapacity the threshold to bound the map by
* @throws IllegalArgumentException if the maximumCapacity is negative
*/
public CacheBuilder maximumCapacity(int maximumCapacity) {
if (maximumCapacity < 0) {
throw new IllegalArgumentException();
}
this.maximumCapacity = maximumCapacity;
return this;
}
/**
* Specifies the estimated number of concurrently updating threads. The
* implementation performs internal sizing to try to accommodate this many
* threads (default 16).
*
* @param concurrencyLevel the estimated number of concurrently updating
* threads
* @throws IllegalArgumentException if the concurrencyLevel is less than or
* equal to zero
*/
public CacheBuilder concurrencyLevel(int concurrencyLevel) {
if (concurrencyLevel <= 0) {
throw new IllegalArgumentException();
}
this.concurrencyLevel = concurrencyLevel;
return this;
}
/**
* Creates a new cache instance.
*
* @param cache the type of cache to construct
* @throws IllegalStateException if the maximum weighted capacity was
* not set
*/
public ConcurrentMap makeCache(Cache cache) {
if (maximumCapacity < 0) {
throw new IllegalStateException();
}
return cache.create(this);
}
}
././@LongLink 0000000 0000000 0000000 00000000210 00000000000 011556 L ustar root root libconcurrentlinkedhashmap-java-1.1~jdk5.orig/unittest/src/java/com/googlecode/concurrentlinkedhashmap/caches/BoundedLinkedHashMap.java libconcurrentlinkedhashmap-java-1.1~jdk5.orig/unittest/src/java/com/googlecode/concurrentlinkedhashm0000600 0000000 0000000 00000003131 11464441225 031257 0 ustar package com.googlecode.concurrentlinkedhashmap.caches;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
/**
* A non-thread safe bounded {@link LinkedHashMap}.
*
* @author ben.manes@gmail.com (Ben Manes)
*/
final class BoundedLinkedHashMap