You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pc...@apache.org on 2006/07/01 00:37:29 UTC
svn commit: r418401 [14/32] - in /incubator/openjpa/trunk: openjpa-lib/
openjpa-lib/src/main/java/org/apache/openjpa/lib/ant/
openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/
openjpa-lib/src/main/java/org/apache/openjpa/lib/jdbc/ openjpa-lib/src/...
Modified: incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/ConcurrentLinkedQueue.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/ConcurrentLinkedQueue.java?rev=418401&r1=418400&r2=418401&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/ConcurrentLinkedQueue.java (original)
+++ incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/ConcurrentLinkedQueue.java Fri Jun 30 15:37:18 2006
@@ -1,19 +1,15 @@
/*
* Copyright 2006 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * Licensed 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
+ * 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.
*/
-
/*
* Written by Doug Lea with assistance from members of JCP JSR-166
* Expert Group and released to the public domain, as explained at
@@ -22,15 +18,13 @@
package org.apache.openjpa.lib.util.concurrent;
import java.io.*;
-
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
-
/**
* An unbounded thread-safe {@linkplain Queue queue} based on linked nodes.
- * This queue orders elements FIFO (first-in-first-out).
+ * This queue orders elements FIFO(first-in-first-out).
* The <em>head</em> of the queue is that element that has been on the
* queue the longest time.
* The <em>tail</em> of the queue is that element that has been on the
@@ -40,75 +34,102 @@
* A <tt>ConcurrentLinkedQueue</tt> is an appropriate choice when
* many threads will share access to a common collection.
* This queue does not permit <tt>null</tt> elements.
- *
- * <p>This implementation employs an efficient "wait-free"
+ * This implementation employs an efficient "wait-free"
* algorithm based on one described in <a
* href="http://www.cs.rochester.edu/u/michael/PODC96.html"> Simple,
* Fast, and Practical Non-Blocking and Blocking Concurrent Queue
* Algorithms</a> by Maged M. Michael and Michael L. Scott.
- *
- * <p>Beware that, unlike in most collections, the <tt>size</tt> method
+ * Beware that, unlike in most collections, the <tt>size</tt> method
* is <em>NOT</em> a constant-time operation. Because of the
* asynchronous nature of these queues, determining the current number
* of elements requires a traversal of the elements.
- *
- * <p>This class and its iterator implement all of the
+ * This class and its iterator implement all of the
* <em>optional</em> methods of the {@link Collection} and {@link
* Iterator} interfaces.
- *
- * <p>Memory consistency effects: As with other concurrent
+ * Memory consistency effects: As with other concurrent
* collections, actions in a thread prior to placing an object into a
* {@code ConcurrentLinkedQueue}
* <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
* actions subsequent to the access or removal of that element from
* the {@code ConcurrentLinkedQueue} in another thread.
- *
- * <p>This class is a member of the
+ * This class is a member of the
* <a href="{@docRoot}/../guide/collections/index.html">
* Java Collections Framework</a>.
- *
+ *
* @since 1.5
* @author Doug Lea
*/
-public class ConcurrentLinkedQueue extends AbstractQueue implements Queue,
- java.io.Serializable {
+public class ConcurrentLinkedQueue extends AbstractQueue
+ implements Queue, java.io.Serializable {
private static final long serialVersionUID = 196745693267521676L;
+
private final Object headLock = new SerializableLock();
private final Object tailLock = new SerializableLock();
- /**
- * Pointer to header node, initialized to a dummy node. The first
- * actual node is at head.getNext().
+ /*
+ * This is a straight adaptation of Michael & Scott algorithm.
+ * For explanation, read the paper. The only(minor) algorithmic
+ * difference is that this version supports lazy deletion of
+ * internal nodes(method remove(Object)) -- remove CAS'es item
+ * fields to null. The normal queue operations unlink but then
+ * pass over nodes with null item fields. Similarly, iteration
+ * methods ignore those with nulls.
+ * Also note that like most non-blocking algorithms in this
+ * package, this implementation relies on the fact that in garbage
+ * collected systems, there is no possibility of ABA problems due
+ * to recycled nodes, so there is no need to use "counted
+ * pointers" or related techniques seen in versions used in
+ * non-GC'ed settings.
*/
- private transient volatile Node head = new Node(null, null);
- /** Pointer to last node on list **/
- private transient volatile Node tail = head;
+ private static class Node {
+ private volatile Object item;
+ private volatile Node next;
- /**
- * Creates a <tt>ConcurrentLinkedQueue</tt> that is initially empty.
- */
- public ConcurrentLinkedQueue() {
- }
+ Node(Object x) { item = x; }
+
+ Node(Object x, Node n) { item = x; next = n; }
+
+ Object getItem() {
+ return item;
+ }
+
+ synchronized boolean casItem(Object cmp, Object val) {
+ if (item == cmp) {
+ item = val;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ synchronized void setItem(Object val) {
+ item = val;
+ }
+
+ Node getNext() {
+ return next;
+ }
+
+ synchronized boolean casNext(Node cmp, Node val) {
+ if (next == cmp) {
+ next = val;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ synchronized void setNext(Node val) {
+ next = val;
+ }
- /**
- * Creates a <tt>ConcurrentLinkedQueue</tt>
- * initially containing the elements of the given collection,
- * added in traversal order of the collection's iterator.
- * @param c the collection of elements to initially contain
- * @throws NullPointerException if the specified collection or any
- * of its elements are null
- */
- public ConcurrentLinkedQueue(Collection c) {
- for (Iterator it = c.iterator(); it.hasNext();)
- add(it.next());
}
private boolean casTail(Node cmp, Node val) {
synchronized (tailLock) {
if (tail == cmp) {
tail = val;
-
return true;
} else {
return false;
@@ -120,7 +141,6 @@
synchronized (headLock) {
if (head == cmp) {
head = val;
-
return true;
} else {
return false;
@@ -128,11 +148,38 @@
}
}
+ /**
+ * Pointer to header node, initialized to a dummy node. The first
+ * actual node is at head.getNext().
+ */
+ private transient volatile Node head = new Node(null, null);
+
+ /** Pointer to last node on list **/
+ private transient volatile Node tail = head;
+
+ /* *
+ * Creates a <tt>ConcurrentLinkedQueue</tt> that is initially empty.
+ */
+ public ConcurrentLinkedQueue() {}
+
+ /**
+ * Creates a <tt>ConcurrentLinkedQueue</tt>
+ * initially containing the elements of the given collection,
+ * added in traversal order of the collection's iterator.
+ * @param c the collection of elements to initially contain
+ * @throws NullPointerException if the specified collection or any
+ * of its elements are null
+ */
+ public ConcurrentLinkedQueue(Collection c) {
+ for (Iterator it = c.iterator(); it.hasNext();)
+ add(it.next());
+ }
+
// Have to override just to update the javadoc
/**
* Inserts the specified element at the tail of this queue.
- *
+ *
* @return <tt>true</tt> (as specified by {@link Collection#add})
* @throws NullPointerException if the specified element is null
*/
@@ -142,26 +189,20 @@
/**
* Inserts the specified element at the tail of this queue.
- *
+ *
* @return <tt>true</tt> (as specified by {@link Queue#offer})
* @throws NullPointerException if the specified element is null
*/
public boolean offer(Object e) {
- if (e == null) {
- throw new NullPointerException();
- }
-
+ if (e == null) throw new NullPointerException();
Node n = new Node(e, null);
-
- for (;;) {
+ for(;;) {
Node t = tail;
Node s = t.getNext();
-
if (t == tail) {
if (s == null) {
if (t.casNext(s, n)) {
casTail(t, n);
-
return true;
}
} else {
@@ -176,23 +217,18 @@
Node h = head;
Node t = tail;
Node first = h.getNext();
-
if (h == head) {
if (h == t) {
- if (first == null) {
+ if (first == null)
return null;
- } else {
+ else
casTail(t, first);
- }
} else if (casHead(h, first)) {
Object item = first.getItem();
-
if (item != null) {
first.setItem(null);
-
return item;
}
-
// else skip over deleted item, continue loop,
}
}
@@ -200,36 +236,31 @@
}
public Object peek() { // same as poll except don't remove item
-
for (;;) {
Node h = head;
Node t = tail;
Node first = h.getNext();
-
if (h == head) {
if (h == t) {
- if (first == null) {
+ if (first == null)
return null;
- } else {
+ else
casTail(t, first);
- }
} else {
Object item = first.getItem();
-
- if (item != null) {
+ if (item != null)
return item;
- } else { // remove deleted node and continue
+ else // remove deleted node and continue
casHead(h, first);
- }
}
}
}
}
/**
- * Returns the first actual (non-header) node on list. This is yet
+ * Returns the first actual(non-header) node on list. This is yet
* another variant of poll/peek; here returning out the first
- * node, not element (so we cannot collapse with peek() without
+ * node, not element(so we cannot collapse with peek() without
* introducing race.)
*/
Node first() {
@@ -237,20 +268,17 @@
Node h = head;
Node t = tail;
Node first = h.getNext();
-
if (h == head) {
if (h == t) {
- if (first == null) {
+ if (first == null)
return null;
- } else {
+ else
casTail(t, first);
- }
} else {
- if (first.getItem() != null) {
+ if (first.getItem() != null)
return first;
- } else { // remove deleted node and continue
+ else // remove deleted node and continue
casHead(h, first);
- }
}
}
}
@@ -258,7 +286,7 @@
/**
* Returns <tt>true</tt> if this queue contains no elements.
- *
+ *
* @return <tt>true</tt> if this queue contains no elements
*/
public boolean isEmpty() {
@@ -266,29 +294,25 @@
}
/**
- * Returns the number of elements in this queue. If this queue
+ * Returns the number of elements in this queue. If this queue
* contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
* <tt>Integer.MAX_VALUE</tt>.
- *
- * <p>Beware that, unlike in most collections, this method is
+ * Beware that, unlike in most collections, this method is
* <em>NOT</em> a constant-time operation. Because of the
* asynchronous nature of these queues, determining the current
* number of elements requires an O(n) traversal.
- *
+ *
* @return the number of elements in this queue
*/
public int size() {
int count = 0;
-
for (Node p = first(); p != null; p = p.getNext()) {
if (p.getItem() != null) {
// Collections.size() spec says to max out
- if (++count == Integer.MAX_VALUE) {
+ if (++count == Integer.MAX_VALUE)
break;
- }
}
}
-
return count;
}
@@ -296,50 +320,38 @@
* Returns <tt>true</tt> if this queue contains the specified element.
* More formally, returns <tt>true</tt> if and only if this queue contains
* at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
- *
+ *
* @param o object to be checked for containment in this queue
* @return <tt>true</tt> if this queue contains the specified element
*/
public boolean contains(Object o) {
- if (o == null) {
- return false;
- }
-
+ if (o == null) return false;
for (Node p = first(); p != null; p = p.getNext()) {
Object item = p.getItem();
-
- if ((item != null) && o.equals(item)) {
+ if (item != null && o.equals(item))
return true;
- }
}
-
return false;
}
/**
* Removes a single instance of the specified element from this queue,
- * if it is present. More formally, removes an element <tt>e</tt> such
+ * if it is present. More formally, removes an element <tt>e</tt> such
* that <tt>o.equals(e)</tt>, if this queue contains one or more such
* elements.
* Returns <tt>true</tt> if this queue contained the specified element
* (or equivalently, if this queue changed as a result of the call).
- *
+ *
* @param o element to be removed from this queue, if present
* @return <tt>true</tt> if this queue changed as a result of the call
*/
public boolean remove(Object o) {
- if (o == null) {
- return false;
- }
-
+ if (o == null) return false;
for (Node p = first(); p != null; p = p.getNext()) {
Object item = p.getItem();
-
- if ((item != null) && o.equals(item) && p.casItem(item, null)) {
+ if (item != null && o.equals(item) && p.casItem(item, null))
return true;
- }
}
-
return false;
}
@@ -348,131 +360,15 @@
* The returned iterator is a "weakly consistent" iterator that
* will never throw {@link ConcurrentModificationException},
* and guarantees to traverse elements as they existed upon
- * construction of the iterator, and may (but is not guaranteed to)
+ * construction of the iterator, and may(but is not guaranteed to)
* reflect any modifications subsequent to construction.
- *
+ *
* @return an iterator over the elements in this queue in proper sequence
*/
public Iterator iterator() {
return new Itr();
}
- /**
- * Save the state to a stream (that is, serialize it).
- *
- * @serialData All of the elements (each an <tt>E</tt>) in
- * the proper order, followed by a null
- * @param s the stream
- */
- private void writeObject(java.io.ObjectOutputStream s)
- throws java.io.IOException {
- // Write out any hidden stuff
- s.defaultWriteObject();
-
- // Write out all elements in the proper order.
- for (Node p = first(); p != null; p = p.getNext()) {
- Object item = p.getItem();
-
- if (item != null) {
- s.writeObject(item);
- }
- }
-
- // Use trailing null as sentinel
- s.writeObject(null);
- }
-
- /**
- * Reconstitute the Queue instance from a stream (that is,
- * deserialize it).
- * @param s the stream
- */
- private void readObject(java.io.ObjectInputStream s)
- throws java.io.IOException, ClassNotFoundException {
- // Read in capacity, and any hidden stuff
- s.defaultReadObject();
-
- head = new Node(null, null);
- tail = head;
-
- // Read in all elements and place in queue
- for (;;) {
- Object item = s.readObject();
-
- if (item == null) {
- break;
- } else {
- offer(item);
- }
- }
- }
-
- /*
- * This is a straight adaptation of Michael & Scott algorithm.
- * For explanation, read the paper. The only (minor) algorithmic
- * difference is that this version supports lazy deletion of
- * internal nodes (method remove(Object)) -- remove CAS'es item
- * fields to null. The normal queue operations unlink but then
- * pass over nodes with null item fields. Similarly, iteration
- * methods ignore those with nulls.
- *
- * Also note that like most non-blocking algorithms in this
- * package, this implementation relies on the fact that in garbage
- * collected systems, there is no possibility of ABA problems due
- * to recycled nodes, so there is no need to use "counted
- * pointers" or related techniques seen in versions used in
- * non-GC'ed settings.
- */
- private static class Node {
- private volatile Object item;
- private volatile Node next;
-
- Node(Object x) {
- item = x;
- }
-
- Node(Object x, Node n) {
- item = x;
- next = n;
- }
-
- Object getItem() {
- return item;
- }
-
- synchronized boolean casItem(Object cmp, Object val) {
- if (item == cmp) {
- item = val;
-
- return true;
- } else {
- return false;
- }
- }
-
- synchronized void setItem(Object val) {
- item = val;
- }
-
- Node getNext() {
- return next;
- }
-
- synchronized boolean casNext(Node cmp, Node val) {
- if (next == cmp) {
- next = val;
-
- return true;
- } else {
- return false;
- }
- }
-
- synchronized void setNext(Node val) {
- next = val;
- }
- }
-
private class Itr implements Iterator {
/**
* Next node to return item for.
@@ -502,29 +398,22 @@
*/
private Object advance() {
lastRet = nextNode;
-
Object x = nextItem;
Node p = (nextNode == null) ? first() : nextNode.getNext();
-
for (;;) {
if (p == null) {
nextNode = null;
nextItem = null;
-
return x;
}
-
Object item = p.getItem();
-
if (item != null) {
nextNode = p;
nextItem = item;
-
return x;
- } else { // skip over nulls
+ } else // skip over nulls
p = p.getNext();
- }
}
}
@@ -533,26 +422,63 @@
}
public Object next() {
- if (nextNode == null) {
- throw new NoSuchElementException();
- }
-
+ if (nextNode == null) throw new NoSuchElementException();
return advance();
}
public void remove() {
Node l = lastRet;
-
- if (l == null) {
- throw new IllegalStateException();
- }
-
+ if (l == null) throw new IllegalStateException();
// rely on a future traversal to relink.
l.setItem(null);
lastRet = null;
}
}
- private static class SerializableLock implements Serializable {
+ /**
+ * Save the state to a stream(that is, serialize it).
+ *
+ * @serialData All of the elements(each an <tt>E</tt>) in
+ * the proper order, followed by a null
+ * @param s the stream
+ */
+ private void writeObject(java.io.ObjectOutputStream s)
+ throws java.io.IOException {
+
+ // Write out any hidden stuff
+ s.defaultWriteObject();
+
+ // Write out all elements in the proper order.
+ for (Node p = first(); p != null; p = p.getNext()) {
+ Object item = p.getItem();
+ if (item != null)
+ s.writeObject(item);
+ }
+
+ // Use trailing null as sentinel
+ s.writeObject(null);
+ }
+
+ /**
+ * Reconstitute the Queue instance from a stream(that is, deserialize it).
+ * @param s the stream
+ */
+ private void readObject(java.io.ObjectInputStream s)
+ throws java.io.IOException, ClassNotFoundException {
+ // Read in capacity, and any hidden stuff
+ s.defaultReadObject();
+
+ head = new Node(null, null);
+ tail = head;
+ // Read in all elements and place in queue
+ for (;;) {
+ Object item = s.readObject();
+ if (item == null)
+ break;
+ else
+ offer(item);
+ }
}
+
+ private static class SerializableLock implements Serializable {}
}
Modified: incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/ConcurrentMap.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/ConcurrentMap.java?rev=418401&r1=418400&r2=418401&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/ConcurrentMap.java (original)
+++ incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/ConcurrentMap.java Fri Jun 30 15:37:18 2006
@@ -1,13 +1,10 @@
/*
* Copyright 2006 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * Licensed 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
+ * 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
@@ -17,24 +14,23 @@
import java.util.*;
-
/**
- * <p>A highly concurrent map.</p>
- *
- * @author Abe White
+ * A highly concurrent map.
+ *
+ * @author Abe White
*/
public interface ConcurrentMap extends Map {
/**
- * Remove an arbitrary (not strictly random) entry from the map. This
- * allows implementation of concurrent caches with size ceilings.
- *
- * @return the removed entry, or null if map is empty
+ * Remove an arbitrary(not strictly random) entry from the map. This
+ * allows implementation of concurrent caches with size ceilings.
+ *
+ * @return the removed entry, or null if map is empty
*/
public Map.Entry removeRandom();
/**
- * Iterate over map entries, beginning at an arbitrary
- * (not strictly random) entry.
+ * Iterate over map entries, beginning at an arbitrary
+ * (not strictly random) entry.
*/
public Iterator randomEntryIterator();
}
Modified: incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/ConcurrentReferenceHashMap.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/ConcurrentReferenceHashMap.java?rev=418401&r1=418400&r2=418401&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/ConcurrentReferenceHashMap.java (original)
+++ incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/ConcurrentReferenceHashMap.java Fri Jun 30 15:37:18 2006
@@ -1,13 +1,10 @@
/*
* Copyright 2006 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * Licensed 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
+ * 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
@@ -15,13 +12,9 @@
*/
package org.apache.openjpa.lib.util.concurrent;
-import org.apache.openjpa.lib.util.ReferenceMap;
-import org.apache.openjpa.lib.util.SizedMap;
-
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
-
import java.util.AbstractMap;
import java.util.Collection;
import java.util.Iterator;
@@ -29,44 +22,35 @@
import java.util.NoSuchElementException;
import java.util.Random;
import java.util.Set;
-
+import org.apache.openjpa.lib.util.ReferenceMap;
+import org.apache.openjpa.lib.util.SizedMap;
/**
* This class implements a HashMap which has limited synchronization
- * and reference keys or values (but not both). In particular mutators are
+ * and reference keys or values(but not both). In particular mutators are
* generally synchronized while accessors are generally not. Additionally the
* Iterators returned by this class are not "fail-fast", but instead try to
* continue to iterate over the data structure after changes have been
- * made. Finally purging of the reference queue is only done inside
- * mutators.
- *
- * Null keys are not supported if keys use references. Null values are not
+ * made. Finally purging of the reference queue is only done inside mutators.
+ * Null keys are not supported if keys use references. Null values are not
* supported if values use references.
- *
- * This class is based heavily on the WeakHashMap class in the Java
+ * This class is based heavily on the WeakHashMap class in the Java
* collections package.
*/
public class ConcurrentReferenceHashMap extends AbstractMap
implements ConcurrentMap, ReferenceMap, SizedMap, Cloneable {
/**
* Cache of random numbers used in "random" methods, since generating them
- * is expensive. We hope each map changes enough between cycling through
- * this list that the overall effect is random enough.
+ * is expensive. We hope each map changes enough between cycling through
+ * this list that the overall effect is random enough.
*/
static final double[] RANDOMS = new double[1000];
-
static {
Random random = new Random();
-
for (int i = 0; i < RANDOMS.length; i++)
RANDOMS[i] = random.nextDouble();
}
- // Types of Enumerations/Iterations
- private static final int KEYS = 0;
- private static final int VALUES = 1;
- private static final int ENTRIES = 2;
-
/**
* The hash table data.
*/
@@ -112,53 +96,49 @@
*/
private int maxSize = Integer.MAX_VALUE;
- // Views
- private transient Set keySet = null;
- private transient Set entrySet = null;
- private transient Collection values = null;
+ private static boolean eq(Object x, Object y) {
+ return x == y || (x != null && x.equals(y));
+ }
/**
* Constructs a new, empty HashMap with the specified initial
* capacity and the specified load factor.
- *
- * @param keyType the reference type of map keys
- * @param valueType the reference type of map values
+ *
+ * @param keyType the reference type of map keys
+ * @param valueType the reference type of map values
* @param initialCapacity the initial capacity of the HashMap.
* @param loadFactor a number between 0.0 and 1.0.
* @exception IllegalArgumentException if neither keys nor values use hard
- * references, if the initial capacity is less than or equal to zero, or if
- * the load factor is less than or equal to zero
+ * references, if the initial capacity is less than or equal to zero, or if
+ * the load factor is less than or equal to zero
*/
public ConcurrentReferenceHashMap(int keyType, int valueType,
int initialCapacity, float loadFactor) {
if (initialCapacity < 0) {
- throw new IllegalArgumentException("Illegal Initial Capacity: " +
+ throw new IllegalArgumentException("Illegal Initial Capacity: "+
initialCapacity);
}
-
if ((loadFactor > 1) || (loadFactor <= 0)) {
throw new IllegalArgumentException("Illegal Load factor: " +
loadFactor);
}
-
- if ((keyType != HARD) && (valueType != HARD)) {
+ if (keyType != HARD && valueType != HARD) {
throw new IllegalArgumentException("Either keys or values must " +
"use hard references.");
}
-
this.keyType = keyType;
this.valueType = valueType;
this.loadFactor = loadFactor;
table = new Entry[initialCapacity];
- threshold = (int) (initialCapacity * loadFactor);
+ threshold = (int)(initialCapacity * loadFactor);
}
/**
* Constructs a new, empty HashMap with the specified initial capacity
* and default load factor.
- *
- * @param keyType the reference type of map keys
- * @param valueType the reference type of map values
+ *
+ * @param keyType the reference type of map keys
+ * @param valueType the reference type of map values
* @param initialCapacity the initial capacity of the HashMap.
*/
public ConcurrentReferenceHashMap(int keyType, int valueType,
@@ -167,11 +147,10 @@
}
/**
- * Constructs a new, empty HashMap with a default capacity and load
- * factor.
- *
- * @param keyType the reference type of map keys
- * @param valueType the reference type of map values
+ * Constructs a new, empty HashMap with a default capacity and load factor.
+ *
+ * @param keyType the reference type of map keys
+ * @param valueType the reference type of map values
*/
public ConcurrentReferenceHashMap(int keyType, int valueType) {
this(keyType, valueType, 11, 0.75f);
@@ -182,40 +161,34 @@
* Map. The HashMap is created with a capacity of thrice the number
* of entries in the given Map or 11 (whichever is greater), and a
* default load factor.
- *
- * @param keyType the reference type of map keys
- * @param valueType the reference type of map values
+ *
+ * @param keyType the reference type of map keys
+ * @param valueType the reference type of map values
*/
public ConcurrentReferenceHashMap(int keyType, int valueType, Map t) {
- this(keyType, valueType, Math.max(3 * t.size(), 11), 0.75f);
+ this(keyType, valueType, Math.max(3*t.size(), 11), 0.75f);
putAll(t);
}
- private static boolean eq(Object x, Object y) {
- return (x == y) || ((x != null) && x.equals(y));
- }
-
public int getMaxSize() {
return maxSize;
}
public void setMaxSize(int maxSize) {
this.maxSize = (maxSize < 0) ? Integer.MAX_VALUE : maxSize;
-
- if (this.maxSize != Integer.MAX_VALUE) {
+ if (this.maxSize != Integer.MAX_VALUE)
removeOverflow(this.maxSize);
- }
}
public boolean isFull() {
- return (maxSize != Integer.MAX_VALUE) && (size() >= maxSize);
+ return maxSize != Integer.MAX_VALUE && size() >= maxSize;
}
public void overflowRemoved(Object key, Object value) {
}
/**
- * Returns the number of key-value mappings in this Map. This
+ * Returns the number of key-value mappings in this Map. This
* result is a snapshot, and may not reflect unprocessed entries
* that will be removed before next attempted access because they
* are no longer referenced.
@@ -225,7 +198,7 @@
}
/**
- * Returns true if this Map contains no key-value mappings. This
+ * Returns true if this Map contains no key-value mappings. This
* result is a snapshot, and may not reflect unprocessed entries
* that will be removed before next attempted access because they
* are no longer referenced.
@@ -237,74 +210,62 @@
/**
* Returns true if this HashMap maps one or more keys to the specified
* value.
- *
+ *
* @param value value whose presence in this Map is to be tested.
*/
public boolean containsValue(Object value) {
Entry[] tab = table;
- if (value == null) {
- if (valueType != HARD) {
+ if (value==null) {
+ if (valueType != HARD)
return false;
- }
-
- for (int i = tab.length; i-- > 0;)
- for (Entry e = tab[i]; e != null; e = e.getNext())
- if (e.getValue() == null) {
+ for (int i = tab.length ; i-- > 0 ;)
+ for (Entry e = tab[i] ; e != null ; e = e.getNext())
+ if (e.getValue()==null)
return true;
- }
} else {
- for (int i = tab.length; i-- > 0;)
- for (Entry e = tab[i]; e != null; e = e.getNext())
- if (eq(value, e.getValue())) {
+ for (int i = tab.length ; i-- > 0 ;)
+ for (Entry e = tab[i] ; e != null ; e = e.getNext())
+ if (eq(value, e.getValue()))
return true;
- }
}
-
return false;
}
/**
* Returns true if this HashMap contains a mapping for the specified key.
- *
+ *
* @param key key whose presence in this Map is to be tested.
*/
public boolean containsKey(Object key) {
- if ((key == null) && (keyType != HARD)) {
+ if (key == null && keyType != HARD)
return false;
- }
Entry[] tab = table;
int hash = (key == null) ? 0 : key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
-
for (Entry e = tab[index]; e != null; e = e.getNext())
- if ((e.getHash() == hash) && eq(key, e.getKey())) {
+ if (e.getHash()==hash && eq(key, e.getKey()))
return true;
- }
-
return false;
}
/**
* Returns the value to which this HashMap maps the specified key.
* Returns null if the HashMap contains no mapping for this key.
- *
+ *
* @param key key whose associated value is to be returned.
*/
public Object get(Object key) {
- if ((key == null) && (keyType != HARD)) {
+ if (key == null && keyType != HARD)
return null;
- }
Entry[] tab = table;
int hash = (key == null) ? 0 : key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
-
for (Entry e = tab[index]; e != null; e = e.getNext())
- if ((e.getHash() == hash) && eq(key, e.getKey())) {
+ if ((e.getHash() == hash) && eq(key, e.getKey()))
return e.getValue();
- }
return null;
}
@@ -317,21 +278,21 @@
*/
private void rehash() {
int oldCapacity = table.length;
- Entry[] oldMap = table;
+ Entry oldMap[] = table;
- int newCapacity = (oldCapacity * 2) + 1;
- Entry[] newMap = new Entry[newCapacity];
+ int newCapacity = oldCapacity * 2 + 1;
+ Entry newMap[] = new Entry[newCapacity];
- for (int i = oldCapacity; i-- > 0;) {
- for (Entry old = oldMap[i]; old != null;) {
- if (((keyType != HARD) && (old.getKey() == null)) ||
- ((valueType != HARD) && (old.getValue() == null))) {
+ for (int i = oldCapacity ; i-- > 0 ;) {
+ for (Entry old = oldMap[i] ; old != null ; ) {
+ if ((keyType != HARD && old.getKey() == null)
+ || valueType != HARD && old.getValue() == null) {
Entry e = old;
old = old.getNext();
e.setNext(null);
count--;
} else {
- Entry e = (Entry) old.clone(queue);
+ Entry e = (Entry)old.clone(queue);
old = old.getNext();
int index = (e.getHash() & 0x7FFFFFFF) % newCapacity;
@@ -341,7 +302,7 @@
}
}
- threshold = (int) (newCapacity * loadFactor);
+ threshold = (int)(newCapacity * loadFactor);
table = newMap;
}
@@ -349,21 +310,19 @@
* Associates the specified value with the specified key in this HashMap.
* If the HashMap previously contained a mapping for this key, the old
* value is replaced.
- *
+ *
* @param key key with which the specified value is to be associated.
* @param value value to be associated with the specified key.
* @return previous value associated with specified key, or null if there
- * was no mapping for key. A null return can also indicate that
+ * was no mapping for key. A null return can also indicate that
* the HashMap previously associated null with the specified key.
*/
public Object put(Object key, Object value) {
- if (((key == null) && (keyType != HARD)) ||
- ((value == null) && (valueType != HARD))) {
+ if ((key == null && keyType != HARD)
+ || (value == null && valueType != HARD))
throw new IllegalArgumentException("Null references not supported");
- }
int hash = (key == null) ? 0 : key.hashCode();
-
synchronized (this) {
expungeStaleEntries();
@@ -371,24 +330,19 @@
int index = 0;
index = (hash & 0x7FFFFFFF) % tab.length;
-
- for (Entry e = tab[index], prev = null; e != null;
- prev = e, e = e.getNext()) {
+ for (Entry e = tab[index], prev = null; e != null; prev = e,
+ e = e.getNext()) {
if ((e.getHash() == hash) && eq(key, e.getKey())) {
Object old = e.getValue();
-
- if (valueType == HARD) {
+ if (valueType == HARD)
e.setValue(value);
- } else {
+ else {
e = newEntry(hash, e.getKey(), value, e.getNext());
-
- if (prev == null) {
+ if (prev == null)
tab[index] = e;
- } else {
+ else
prev.setNext(e);
- }
}
-
return old;
}
}
@@ -401,14 +355,11 @@
index = (hash & 0x7FFFFFFF) % tab.length;
}
- if (maxSize != Integer.MAX_VALUE) {
+ if (maxSize != Integer.MAX_VALUE)
removeOverflow(maxSize - 1);
- }
-
tab[index] = newEntry(hash, key, value, tab[index]);
count++;
}
-
return null;
}
@@ -417,16 +368,13 @@
*/
private Entry newEntry(int hash, Object key, Object value, Entry next) {
int refType = (keyType != HARD) ? keyType : valueType;
-
- switch (refType) {
+ switch(refType) {
case WEAK:
return new WeakEntry(hash, key, value, refType == keyType, next,
queue);
-
case SOFT:
return new SoftEntry(hash, key, value, refType == keyType, next,
queue);
-
default:
return new HardEntry(hash, key, value, next);
}
@@ -434,59 +382,49 @@
/**
* Remove any entries equal to or over the max size.
- */
+ */
private void removeOverflow(int maxSize) {
while (count > maxSize) {
Map.Entry entry = removeRandom();
-
- if (entry == null) {
+ if (entry == null)
break;
- }
-
overflowRemoved(entry.getKey(), entry.getValue());
}
}
/**
* Removes the mapping for this key from this HashMap if present.
- *
+ *
* @param key key whose mapping is to be removed from the Map.
* @return previous value associated with specified key, or null if there
* was no mapping for key. A null return can also indicate that
* the HashMap previously associated null with the specified key.
*/
public Object remove(Object key) {
- if ((key == null) && (keyType != HARD)) {
+ if (key == null && keyType != HARD)
return null;
- }
int hash = (key == null) ? 0 : key.hashCode();
-
synchronized (this) {
expungeStaleEntries();
Entry[] tab = table;
int index = (hash & 0x7FFFFFFF) % tab.length;
-
for (Entry e = tab[index], prev = null; e != null;
- prev = e, e = e.getNext()) {
+ prev = e, e = e.getNext()) {
if ((e.getHash() == hash) && eq(key, e.getKey())) {
- if (prev != null) {
+ if (prev != null)
prev.setNext(e.getNext());
- }
// otherwise put the bucket after us
- else {
+ else
tab[index] = e.getNext();
- }
count--;
-
return e.getValue();
}
}
}
-
return null;
}
@@ -506,32 +444,24 @@
* Return an arbitrary entry index.
*/
private int randomEntryIndex() {
- if (randomEntry == RANDOMS.length) {
+ if(randomEntry == RANDOMS.length)
randomEntry = 0;
- }
-
- return (int) (RANDOMS[randomEntry++] * table.length);
+ return(int) (RANDOMS[randomEntry++] * table.length);
}
public Map.Entry removeRandom() {
synchronized (this) {
expungeStaleEntries();
-
- if (count == 0) {
+ if (count == 0)
return null;
- }
int random = randomEntryIndex();
- int index = findEntry(random, (random % 2) == 0, false);
-
- if (index == -1) {
+ int index = findEntry(random, random % 2 == 0, false);
+ if (index == -1)
return null;
- }
-
Entry rem = table[index];
table[index] = rem.getNext();
count--;
-
return rem;
}
}
@@ -543,22 +473,16 @@
private int findEntry(int start, boolean forward, boolean searchedOther) {
if (forward) {
for (int i = start; i < table.length; i++)
- if (table[i] != null) {
+ if (table[i] != null)
return i;
- }
-
- return (searchedOther || (start == 0)) ? (-1)
- : findEntry(start - 1,
- false, true);
+ return(searchedOther || start == 0) ? -1
+ : findEntry(start - 1, false, true);
} else {
for (int i = start; i >= 0; i--)
- if (table[i] != null) {
+ if (table[i] != null)
return i;
- }
-
- return (searchedOther || (start == (table.length - 1))) ? (-1)
- : findEntry(start +
- 1, true, true);
+ return(searchedOther || start == table.length - 1) ? -1
+ : findEntry(start + 1, true, true);
}
}
@@ -572,12 +496,11 @@
* Copies all of the mappings from the specified Map to this HashMap
* These mappings will replace any mappings that this HashMap had for any
* of the keys currently in the specified Map.
- *
+ *
* @param t Mappings to be stored in this Map.
*/
public void putAll(Map t) {
Iterator i = t.entrySet().iterator();
-
while (i.hasNext()) {
Map.Entry e = (Map.Entry) i.next();
put(e.getKey(), e.getValue());
@@ -592,10 +515,8 @@
// since table is getting cleared.
while (queue.poll() != null)
;
-
table = new Entry[table.length];
count = 0;
-
// Allocation of array may have caused GC, which may have caused
// additional entries to go stale. Removing these entries from
// the reference queue will make them eligible for reclamation.
@@ -611,27 +532,23 @@
try {
expungeStaleEntries();
- ConcurrentReferenceHashMap t = (ConcurrentReferenceHashMap) super.clone();
+ ConcurrentReferenceHashMap t = (ConcurrentReferenceHashMap)
+ super.clone();
t.table = new Entry[table.length];
-
- for (int i = table.length; i-- > 0;) {
+ for (int i = table.length ; i-- > 0 ; ) {
Entry e = table[i];
-
if (e != null) {
- t.table[i] = (Entry) e.clone(t.queue);
+ t.table[i] = (Entry)e.clone(t.queue);
e = e.getNext();
-
for (Entry k = t.table[i]; e != null; e = e.getNext()) {
- k.setNext((Entry) e.clone(t.queue));
+ k.setNext((Entry)e.clone(t.queue));
k = k.getNext();
}
}
}
-
t.keySet = null;
t.entrySet = null;
t.values = null;
-
return t;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
@@ -639,8 +556,14 @@
}
}
+ // Views
+
+ private transient Set keySet = null;
+ private transient Set entrySet = null;
+ private transient Collection values = null;
+
/**
- * Returns a Set view of the keys contained in this HashMap. The Set is
+ * Returns a Set view of the keys contained in this HashMap. The Set is
* backed by the HashMap, so changes to the HashMap are reflected in the
* Set, and vice-versa. The Set supports element removal, which removes
* the corresponding mapping from the HashMap, via the Iterator.remove,
@@ -650,28 +573,27 @@
public Set keySet() {
if (keySet == null) {
keySet = new java.util.AbstractSet() {
- public Iterator iterator() {
- return new HashIterator(KEYS, table.length - 1);
- }
+ public Iterator iterator() {
+ return new HashIterator(KEYS, table.length - 1);
+ }
- public int size() {
- return count;
- }
+ public int size() {
+ return count;
+ }
- public boolean contains(Object o) {
- return containsKey(o);
- }
+ public boolean contains(Object o) {
+ return containsKey(o);
+ }
- public boolean remove(Object o) {
- return ConcurrentReferenceHashMap.this.remove(o) != null;
- }
+ public boolean remove(Object o) {
+ return ConcurrentReferenceHashMap.this.remove(o) != null;
+ }
- public void clear() {
- ConcurrentReferenceHashMap.this.clear();
- }
- };
+ public void clear() {
+ ConcurrentReferenceHashMap.this.clear();
+ }
+ };
}
-
return keySet;
}
@@ -685,107 +607,95 @@
* operations.
*/
public Collection values() {
- if (values == null) {
+ if (values==null) {
values = new java.util.AbstractCollection() {
- public Iterator iterator() {
- return new HashIterator(VALUES, table.length - 1);
- }
+ public Iterator iterator() {
+ return new HashIterator(VALUES, table.length - 1);
+ }
- public int size() {
- return count;
- }
+ public int size() {
+ return count;
+ }
- public boolean contains(Object o) {
- return containsValue(o);
- }
+ public boolean contains(Object o) {
+ return containsValue(o);
+ }
- public void clear() {
- ConcurrentReferenceHashMap.this.clear();
- }
- };
+ public void clear() {
+ ConcurrentReferenceHashMap.this.clear();
+ }
+ };
}
-
return values;
}
/**
* Returns a Collection view of the mappings contained in this HashMap.
- * Each element in the returned collection is a Map.Entry. The Collection
+ * Each element in the returned collection is a Map.Entry. The Collection
* is backed by the HashMap, so changes to the HashMap are reflected in the
- * Collection, and vice-versa. The Collection supports element removal,
+ * Collection, and vice-versa. The Collection supports element removal,
* which removes the corresponding mapping from the HashMap, via the
* Iterator.remove, Collection.remove, removeAll, retainAll and clear
- * operations. It does not support the add or addAll operations.
- *
- * @see Map.Entry
+ * operations. It does not support the add or addAll operations.
+ *
+ * @see Map.Entry
*/
public Set entrySet() {
- if (entrySet == null) {
+ if (entrySet==null) {
entrySet = new java.util.AbstractSet() {
- public Iterator iterator() {
- return new HashIterator(ENTRIES, table.length - 1);
- }
-
- public boolean contains(Object o) {
- if (!(o instanceof Map.Entry)) {
- return false;
- }
-
- Map.Entry entry = (Map.Entry) o;
- Object key = entry.getKey();
- Entry[] tab = table;
- int hash = ((key == null) ? 0 : key.hashCode());
- int index = (hash & 0x7FFFFFFF) % tab.length;
-
- for (Entry e = tab[index]; e != null;
- e = e.getNext())
- if ((e.getHash() == hash) && eq(e, entry)) {
- return true;
- }
-
- return false;
- }
+ public Iterator iterator() {
+ return new HashIterator(ENTRIES, table.length - 1);
+ }
- public boolean remove(Object o) {
- if (!(o instanceof Map.Entry)) {
- return false;
- }
-
- Map.Entry entry = (Map.Entry) o;
- Object key = entry.getKey();
-
- synchronized (ConcurrentReferenceHashMap.this) {
- Entry[] tab = table;
- int hash = ((key == null) ? 0 : key.hashCode());
- int index = (hash & 0x7FFFFFFF) % tab.length;
-
- for (Entry e = tab[index], prev = null;
- e != null; prev = e, e = e.getNext()) {
- if ((e.getHash() == hash) && eq(e, entry)) {
- if (prev != null) {
- prev.setNext(e.getNext());
- } else {
- tab[index] = e.getNext();
- }
-
- count--;
-
- return true;
- }
- }
+ public boolean contains(Object o) {
+ if (!(o instanceof Map.Entry))
+ return false;
+ Map.Entry entry = (Map.Entry)o;
+ Object key = entry.getKey();
+ Entry[] tab = table;
+ int hash = (key==null ? 0 : key.hashCode());
+ int index = (hash & 0x7FFFFFFF) % tab.length;
+
+ for (Entry e = tab[index]; e != null; e = e.getNext())
+ if (e.getHash()==hash && eq(e, entry))
+ return true;
+ return false;
+ }
- return false;
- }
+ public boolean remove(Object o) {
+ if (!(o instanceof Map.Entry))
+ return false;
+ Map.Entry entry = (Map.Entry)o;
+ Object key = entry.getKey();
+ synchronized (ConcurrentReferenceHashMap.this) {
+ Entry[] tab = table;
+ int hash = (key==null ? 0 : key.hashCode());
+ int index = (hash & 0x7FFFFFFF) % tab.length;
+
+ for (Entry e = tab[index], prev = null; e != null;
+ prev = e, e = e.getNext()) {
+ if (e.getHash()==hash && eq(e, entry)) {
+ if (prev != null)
+ prev.setNext(e.getNext());
+ else
+ tab[index] = e.getNext();
+
+ count--;
+ return true;
+ }
}
+ return false;
+ }
+ }
- public int size() {
- return count;
- }
+ public int size() {
+ return count;
+ }
- public void clear() {
- ConcurrentReferenceHashMap.this.clear();
- }
- };
+ public void clear() {
+ ConcurrentReferenceHashMap.this.clear();
+ }
+ };
}
return entrySet;
@@ -796,44 +706,31 @@
*/
private void expungeStaleEntries() {
Object r;
-
while ((r = queue.poll()) != null) {
- Entry entry = (Entry) r;
+ Entry entry = (Entry)r;
int hash = entry.getHash();
Entry[] tab = table;
int index = (hash & 0x7FFFFFFF) % tab.length;
for (Entry e = tab[index], prev = null; e != null;
- prev = e, e = e.getNext()) {
+ prev = e, e = e.getNext()) {
if (e == entry) {
- if (prev != null) {
+ if (prev != null)
prev.setNext(e.getNext());
- }
// otherwise put the bucket after us
- else {
+ else
tab[index] = e.getNext();
- }
count--;
-
- if (keyType == HARD) {
+ if (keyType == HARD)
valueExpired(e.getKey());
- } else {
+ else
keyExpired(e.getValue());
- }
}
}
}
}
- int capacity() {
- return table.length;
- }
-
- float loadFactor() {
- return loadFactor;
- }
-
/**
* HashMap collision list entry.
*/
@@ -881,7 +778,8 @@
return new HardEntry(hash, key, value, null);
}
- // Map.Entry Ops
+ // Map.Entry Ops
+
public Object getKey() {
return key;
}
@@ -893,26 +791,23 @@
public Object setValue(Object value) {
Object oldValue = this.value;
this.value = value;
-
return oldValue;
}
public boolean equals(Object o) {
- if (!(o instanceof Map.Entry)) {
- return false;
- }
-
- Map.Entry e = (Map.Entry) o;
+ if (!(o instanceof Map.Entry)) return false;
+ Map.Entry e = (Map.Entry)o;
Object k1 = key;
Object k2 = e.getKey();
- return ((k1 == null) ? (k2 == null) : eq(k1, k2)) &&
- ((value == null) ? (e.getValue() == null) : eq(value, e.getValue()));
+ return(k1 == null ? k2 == null : eq(k1, k2)) &&
+ (value == null ? e.getValue() == null
+ : eq(value, e.getValue()));
}
public int hashCode() {
- return hash ^ ((value == null) ? 0 : value.hashCode());
+ return hash ^ (value==null ? 0 : value.hashCode());
}
public String toString() {
@@ -953,43 +848,38 @@
public Object clone(ReferenceQueue queue) {
// It is the callers responsibility to set the next field
// correctly.
- return new WeakEntry(hash, getKey(), getValue(), keyRef, null, queue);
+ return new WeakEntry(hash, getKey(), getValue(), keyRef, null,
+ queue);
}
- // Map.Entry Ops
+ // Map.Entry Ops
+
public Object getKey() {
- return (keyRef) ? super.get() : hard;
+ return(keyRef) ? super.get() : hard;
}
public Object getValue() {
- return (keyRef) ? hard : super.get();
+ return(keyRef) ? hard : super.get();
}
public Object setValue(Object value) {
- if (!keyRef) {
+ if (!keyRef)
throw new Error("Attempt to reset reference value.");
- }
Object oldValue = hard;
hard = value;
-
return oldValue;
}
public boolean equals(Object o) {
- if (!(o instanceof Map.Entry)) {
- return false;
- }
-
- Map.Entry e = (Map.Entry) o;
-
+ if (!(o instanceof Map.Entry)) return false;
+ Map.Entry e = (Map.Entry)o;
return eq(getKey(), e.getKey()) && eq(getValue(), e.getValue());
}
public int hashCode() {
Object val = getValue();
-
- return hash ^ ((val == null) ? 0 : val.hashCode());
+ return hash ^ (val==null ? 0 : val.hashCode());
}
public String toString() {
@@ -1030,43 +920,38 @@
public Object clone(ReferenceQueue queue) {
// It is the callers responsibility to set the next field
// correctly.
- return new SoftEntry(hash, getKey(), getValue(), keyRef, null, queue);
+ return new SoftEntry(hash, getKey(), getValue(), keyRef, null,
+ queue);
}
- // Map.Entry Ops
+ // Map.Entry Ops
+
public Object getKey() {
- return (keyRef) ? super.get() : hard;
+ return(keyRef) ? super.get() : hard;
}
public Object getValue() {
- return (keyRef) ? hard : super.get();
+ return(keyRef) ? hard : super.get();
}
public Object setValue(Object value) {
- if (!keyRef) {
+ if (!keyRef)
throw new Error("Attempt to reset reference value.");
- }
Object oldValue = hard;
hard = value;
-
return oldValue;
}
public boolean equals(Object o) {
- if (!(o instanceof Map.Entry)) {
- return false;
- }
-
- Map.Entry e = (Map.Entry) o;
-
+ if (!(o instanceof Map.Entry)) return false;
+ Map.Entry e = (Map.Entry)o;
return eq(getKey(), e.getKey()) && eq(getValue(), e.getValue());
}
public int hashCode() {
Object val = getValue();
-
- return hash ^ ((val == null) ? 0 : val.hashCode());
+ return hash ^ (val==null ? 0 : val.hashCode());
}
public String toString() {
@@ -1074,8 +959,13 @@
}
}
+ // Types of Enumerations/Iterations
+ private static final int KEYS = 0;
+ private static final int VALUES = 1;
+ private static final int ENTRIES = 2;
+
/**
- * Map iterator.
+ * Map iterator.
*/
private class HashIterator implements Iterator {
final Entry[] table = ConcurrentReferenceHashMap.this.table;
@@ -1096,66 +986,61 @@
if (entry != null) {
return true;
}
-
while (index >= stopIndex) {
if ((entry = table[index--]) != null) {
return true;
}
}
-
if (stopIndex == 0) {
index = table.length - 1;
stopIndex = startIndex + 1;
-
while (index >= stopIndex) {
if ((entry = table[index--]) != null) {
return true;
}
}
}
-
return false;
}
public Object next() {
- if (!hasNext()) {
+ if (!hasNext())
throw new NoSuchElementException();
- }
-
Entry e = lastReturned = entry;
entry = e.getNext();
-
- return (type == KEYS) ? e.getKey()
- : ((type == VALUES) ? e.getValue() : e);
+ return type == KEYS ? e.getKey()
+ : (type == VALUES ? e.getValue() : e);
}
public void remove() {
- if (lastReturned == null) {
+ if (lastReturned == null)
throw new IllegalStateException();
- }
-
synchronized (ConcurrentReferenceHashMap.this) {
Entry[] tab = ConcurrentReferenceHashMap.this.table;
int index = (lastReturned.getHash() & 0x7FFFFFFF) % tab.length;
for (Entry e = tab[index], prev = null; e != null;
- prev = e, e = e.getNext()) {
+ prev = e, e = e.getNext()) {
if (e == lastReturned) {
- if (prev == null) {
+ if (prev == null)
tab[index] = e.getNext();
- } else {
+ else
prev.setNext(e.getNext());
- }
-
count--;
lastReturned = null;
-
return;
}
}
-
throw new Error("Iterated off table when doing remove");
}
}
+ }
+
+ int capacity() {
+ return table.length;
+ }
+
+ float loadFactor() {
+ return loadFactor;
}
}
Modified: incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/ConcurrentReferenceHashSet.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/ConcurrentReferenceHashSet.java?rev=418401&r1=418400&r2=418401&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/ConcurrentReferenceHashSet.java (original)
+++ incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/ConcurrentReferenceHashSet.java Fri Jun 30 15:37:18 2006
@@ -1,13 +1,10 @@
/*
* Copyright 2006 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * Licensed 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
+ * 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
@@ -15,50 +12,48 @@
*/
package org.apache.openjpa.lib.util.concurrent;
-import org.apache.commons.collections.map.*;
-import org.apache.commons.collections.set.*;
-
import java.io.*;
-
import java.util.*;
-
+import org.apache.commons.collections.map.*;
+import org.apache.commons.collections.set.*;
/**
- * <p>A concurrent set whose values may be stored as weak or soft
- * references.</p>
- *
- * @author Abe White
- * @nojavadoc */
+ * A concurrent set whose values may be stored as weak or soft references.
+ *
+ * @author Abe White
+ * @nojavadoc
+ */
public class ConcurrentReferenceHashSet implements Set, Serializable {
/**
- * Hard reference marker.
- */
+ * Hard reference marker.
+ */
public static final int HARD = 0;
/**
- * Soft reference marker.
- */
+ * Soft reference marker.
+ */
public static final int SOFT = 1;
/**
- * Weak reference marker.
+ * Weak reference marker.
*/
public static final int WEAK = 2;
+
private static final Object DUMMY_VAL = new Object();
+
private final Set _set;
/**
- * Construct a set with the given reference type.
+ * Construct a set with the given reference type.
*/
public ConcurrentReferenceHashSet(int refType) {
- if (refType == HARD) {
+ if (refType == HARD)
_set = MapBackedSet.decorate(new ConcurrentHashMap(), DUMMY_VAL);
- } else {
- int mapRefType = (refType == WEAK)
- ? ConcurrentReferenceHashMap.WEAK
+ else {
+ int mapRefType = (refType == WEAK) ? ConcurrentReferenceHashMap.WEAK
: ConcurrentReferenceHashMap.SOFT;
- _set = MapBackedSet.decorate(new ConcurrentReferenceHashMap(
- mapRefType, ConcurrentReferenceHashMap.HARD), DUMMY_VAL);
+ _set = MapBackedSet.decorate(new ConcurrentReferenceHashMap
+ (mapRefType, ConcurrentReferenceHashMap.HARD), DUMMY_VAL);
}
}
@@ -119,14 +114,10 @@
}
public boolean equals(Object obj) {
- if (this == obj) {
+ if (this == obj)
return true;
- }
-
- if (obj instanceof ConcurrentReferenceHashSet) {
+ if (obj instanceof ConcurrentReferenceHashSet)
obj = ((ConcurrentReferenceHashSet) obj)._set;
- }
-
return _set.equals(obj);
}
}
Modified: incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/CondVar.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/CondVar.java?rev=418401&r1=418400&r2=418401&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/CondVar.java (original)
+++ incubator/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/CondVar.java Fri Jun 30 15:37:18 2006
@@ -1,19 +1,15 @@
/*
* Copyright 2006 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * Licensed 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
+ * 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.
*/
-
/*
* Originally written by Doug Lea and released into the public domain.
* This may be used for any purposes whatsoever without acknowledgment.
@@ -24,14 +20,13 @@
import java.util.*;
-
class CondVar implements Condition, java.io.Serializable {
+
/** The lock */
- protected final ExclusiveLock lock;
+ protected final ExclusiveLock lock;
- /**
- * Create a new CondVar that relies on the given mutual
- * exclusion lock.
+ /* *
+ * Create a new CondVar that relies on the given mutual exclusion lock.
* @param lock A non-reentrant mutual exclusion lock.
*/
CondVar(ExclusiveLock lock) {
@@ -40,23 +35,17 @@
public void awaitUninterruptibly() {
int holdCount = lock.getHoldCount();
-
if (holdCount == 0) {
throw new IllegalMonitorStateException();
}
-
// avoid instant spurious wakeup if thread already interrupted
boolean wasInterrupted = Thread.interrupted();
-
try {
synchronized (this) {
- for (int i = holdCount; i > 0; i--)
- lock.unlock();
-
+ for (int i=holdCount; i>0; i--) lock.unlock();
while (true) {
try {
wait();
-
break;
} catch (InterruptedException ex) {
wasInterrupted = true;
@@ -66,10 +55,9 @@
}
}
}
- } finally {
- for (int i = holdCount; i > 0; i--)
- lock.lock();
-
+ }
+ finally {
+ for (int i=holdCount; i>0; i--) lock.lock();
if (wasInterrupted) {
Thread.currentThread().interrupt();
}
@@ -78,20 +66,13 @@
public void await() throws InterruptedException {
int holdCount = lock.getHoldCount();
-
if (holdCount == 0) {
throw new IllegalMonitorStateException();
}
-
- if (Thread.interrupted()) {
- throw new InterruptedException();
- }
-
+ if (Thread.interrupted()) throw new InterruptedException();
try {
synchronized (this) {
- for (int i = holdCount; i > 0; i--)
- lock.unlock();
-
+ for (int i=holdCount; i>0; i--) lock.unlock();
try {
wait();
} catch (InterruptedException ex) {
@@ -99,102 +80,81 @@
throw ex;
}
}
- } finally {
- for (int i = holdCount; i > 0; i--)
- lock.lock();
+ }
+ finally {
+ for (int i=holdCount; i>0; i--) lock.lock();
}
}
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
int holdCount = lock.getHoldCount();
-
if (holdCount == 0) {
throw new IllegalMonitorStateException();
}
-
- if (Thread.interrupted()) {
- throw new InterruptedException();
- }
-
+ if (Thread.interrupted()) throw new InterruptedException();
long nanos = unit.toNanos(timeout);
boolean success = false;
-
try {
synchronized (this) {
- for (int i = holdCount; i > 0; i--)
- lock.unlock();
-
+ for (int i=holdCount; i>0; i--) lock.unlock();
try {
if (nanos > 0) {
long start = Utils.nanoTime();
TimeUnit.NANOSECONDS.timedWait(this, nanos);
- // DK: due to coarse-grained (millis) clock, it seems
- // preferable to acknowledge timeout (success == false)
- // when the equality holds (timing is exact)
- success = (Utils.nanoTime() - start) < nanos;
+ // DK: due to coarse-grained(millis) clock, it seems
+ // preferable to acknowledge timeout(success == false)
+ // when the equality holds(timing is exact)
+ success = Utils.nanoTime() - start < nanos;
}
} catch (InterruptedException ex) {
notify();
throw ex;
}
}
- } finally {
- for (int i = holdCount; i > 0; i--)
- lock.lock();
}
-
+ finally {
+ for (int i=holdCount; i>0; i--) lock.lock();
+ }
return success;
}
- // public long awaitNanos(long timeout) throws InterruptedException {
- // throw new UnsupportedOperationException();
- // }
- public boolean awaitUntil(Date deadline) throws InterruptedException {
- if (deadline == null) {
- throw new NullPointerException();
- }
+// public long awaitNanos(long timeout) throws InterruptedException {
+// throw new UnsupportedOperationException();
+// }
+ public boolean awaitUntil(Date deadline) throws InterruptedException {
+ if (deadline == null) throw new NullPointerException();
int holdCount = lock.getHoldCount();
-
if (holdCount == 0) {
throw new IllegalMonitorStateException();
}
-
long abstime = deadline.getTime();
-
- if (Thread.interrupted()) {
- throw new InterruptedException();
- }
+ if (Thread.interrupted()) throw new InterruptedException();
boolean success = false;
-
try {
synchronized (this) {
- for (int i = holdCount; i > 0; i--)
- lock.unlock();
-
+ for (int i=holdCount; i>0; i--) lock.unlock();
try {
long start = System.currentTimeMillis();
long msecs = abstime - start;
-
if (msecs > 0) {
wait(msecs);
- // DK: due to coarse-grained (millis) clock, it seems
- // preferable to acknowledge timeout (success == false)
- // when the equality holds (timing is exact)
- success = (System.currentTimeMillis() - start) < msecs;
+ // DK: due to coarse-grained(millis) clock, it seems
+ // preferable to acknowledge timeout(success == false)
+ // when the equality holds(timing is exact)
+ success = System.currentTimeMillis() - start < msecs;
}
} catch (InterruptedException ex) {
notify();
throw ex;
}
}
- } finally {
- for (int i = holdCount; i > 0; i--)
- lock.lock();
}
-
+ finally {
+ for (int i=holdCount; i>0; i--) lock.lock();
+ }
return success;
}
@@ -202,7 +162,6 @@
if (!lock.isHeldByCurrentThread()) {
throw new IllegalMonitorStateException();
}
-
notify();
}
@@ -210,13 +169,10 @@
if (!lock.isHeldByCurrentThread()) {
throw new IllegalMonitorStateException();
}
-
notifyAll();
}
- protected ExclusiveLock getLock() {
- return lock;
- }
+ protected ExclusiveLock getLock() { return lock; }
protected boolean hasWaiters() {
throw new UnsupportedOperationException("Use FAIR version");
@@ -232,7 +188,6 @@
static interface ExclusiveLock extends Lock {
boolean isHeldByCurrentThread();
-
int getHoldCount();
}
}