167 |
|
* estimated to be less than the given threshold. Using a value of |
168 |
|
* {@code Long.MAX_VALUE} suppresses all parallelism. Using a value |
169 |
|
* of {@code 1} results in maximal parallelism by partitioning into |
170 |
< |
* enough subtasks to utilize all processors. Normally, you would |
171 |
< |
* initially choose one of these extreme values, and then measure |
172 |
< |
* performance of using in-between values that trade off overhead |
173 |
< |
* versus throughput. Parallel forms use the {@link |
174 |
< |
* ForkJoinPool#commonPool()}. |
170 |
> |
* enough subtasks to fully utilize the {@link |
171 |
> |
* ForkJoinPool#commonPool()} that is used for all parallel |
172 |
> |
* computations. Normally, you would initially choose one of these |
173 |
> |
* extreme values, and then measure performance of using in-between |
174 |
> |
* values that trade off overhead versus throughput. |
175 |
|
* |
176 |
|
* <p>The concurrency properties of bulk operations follow |
177 |
|
* from those of ConcurrentHashMap: Any non-null result returned |
683 |
|
} |
684 |
|
|
685 |
|
/** |
686 |
< |
* Returns a Class for the given object of the form "class C |
686 |
> |
* Returns a Class for the given type of the form "class C |
687 |
|
* implements Comparable<C>", if one exists, else null. See below |
688 |
|
* for explanation. |
689 |
|
*/ |
690 |
< |
static Class<?> comparableClassFor(Object x) { |
691 |
< |
Class<?> c, s, cmpc; Type[] ts, as; Type t; ParameterizedType p; |
692 |
< |
if ((c = x.getClass()) == String.class) // bypass checks |
690 |
> |
static Class<?> comparableClassFor(Class<?> c) { |
691 |
> |
Class<?> s, cmpc; Type[] ts, as; Type t; ParameterizedType p; |
692 |
> |
if (c == String.class) // bypass checks |
693 |
|
return c; |
694 |
< |
if ((cmpc = Comparable.class).isAssignableFrom(c)) { |
694 |
> |
if (c != null && (cmpc = Comparable.class).isAssignableFrom(c)) { |
695 |
|
while (cmpc.isAssignableFrom(s = c.getSuperclass())) |
696 |
|
c = s; // find topmost comparable class |
697 |
|
if ((ts = c.getGenericInterfaces()) != null) { |
790 |
|
final TreeNode<K,V> getTreeNode(int h, Object k, TreeNode<K,V> p, |
791 |
|
Class<?> cc) { |
792 |
|
while (p != null) { |
793 |
< |
int dir, ph; Object pk; |
793 |
> |
int dir, ph; Object pk; Class<?> pc; |
794 |
|
if ((ph = p.hash) != h) |
795 |
|
dir = (h < ph) ? -1 : 1; |
796 |
|
else if ((pk = p.key) == k || k.equals(pk)) |
797 |
|
return p; |
798 |
< |
else if (cc == null || comparableClassFor(pk) != cc || |
798 |
> |
else if (cc == null || pk == null || |
799 |
> |
((pc = pk.getClass()) != cc && |
800 |
> |
comparableClassFor(pc) != cc) || |
801 |
|
(dir = ((Comparable<Object>)k).compareTo(pk)) == 0) { |
802 |
|
TreeNode<K,V> r, pr; // check both sides |
803 |
|
if ((pr = p.right) != null && |
817 |
|
* lock, searches along next links. |
818 |
|
*/ |
819 |
|
final V getValue(int h, Object k) { |
820 |
< |
Class<?> cc = comparableClassFor(k); |
820 |
> |
Class<?> cc = comparableClassFor(k.getClass()); |
821 |
|
Node<K,V> r = null; |
822 |
|
for (Node<K,V> e = first; e != null; e = e.next) { |
823 |
|
long s; |
842 |
|
* @return null if added |
843 |
|
*/ |
844 |
|
final TreeNode<K,V> putTreeNode(int h, Object k, V v) { |
845 |
< |
Class<?> cc = comparableClassFor(k); |
845 |
> |
Class<?> cc = comparableClassFor(k.getClass()); |
846 |
|
TreeNode<K,V> pp = root, p = null; |
847 |
|
int dir = 0; |
848 |
|
while (pp != null) { // find existing node or leaf to insert at |
849 |
< |
int ph; Object pk; |
849 |
> |
int ph; Object pk; Class<?> pc; |
850 |
|
p = pp; |
851 |
|
if ((ph = p.hash) != h) |
852 |
|
dir = (h < ph) ? -1 : 1; |
853 |
|
else if ((pk = p.key) == k || k.equals(pk)) |
854 |
|
return p; |
855 |
< |
else if (cc == null || comparableClassFor(pk) != cc || |
855 |
> |
else if (cc == null || pk == null || |
856 |
> |
((pc = pk.getClass()) != cc && |
857 |
> |
comparableClassFor(pc) != cc) || |
858 |
|
(dir = ((Comparable<Object>)k).compareTo(pk)) == 0) { |
859 |
|
TreeNode<K,V> r, pr; |
860 |
|
if ((pr = p.right) != null && |
1175 |
|
* only when locked. |
1176 |
|
*/ |
1177 |
|
private final void replaceWithTreeBin(Node<K,V>[] tab, int index, Object key) { |
1178 |
< |
if (tab != null && comparableClassFor(key) != null) { |
1178 |
> |
if (tab != null && comparableClassFor(key.getClass()) != null) { |
1179 |
|
TreeBin<K,V> t = new TreeBin<K,V>(); |
1180 |
|
for (Node<K,V> e = tabAt(tab, index); e != null; e = e.next) |
1181 |
|
t.putTreeNode(e.hash, e.key, e.val); |
1237 |
|
try { |
1238 |
|
if (tabAt(tab, i) == f) { |
1239 |
|
validated = true; |
1240 |
< |
Class<?> cc = comparableClassFor(k); |
1240 |
> |
Class<?> cc = comparableClassFor(k.getClass()); |
1241 |
|
TreeNode<K,V> p = t.getTreeNode(h, k, t.root, cc); |
1242 |
|
if (p != null) { |
1243 |
|
V pv = p.val; |
1435 |
|
try { |
1436 |
|
if (tabAt(tab, i) == f) { |
1437 |
|
len = 2; |
1438 |
< |
Class<?> cc = comparableClassFor(k); |
1438 |
> |
Class<?> cc = comparableClassFor(k.getClass()); |
1439 |
|
TreeNode<K,V> p = t.getTreeNode(h, k, t.root, cc); |
1440 |
|
if (p != null) |
1441 |
|
val = p.val; |
1534 |
|
try { |
1535 |
|
if (tabAt(tab, i) == f) { |
1536 |
|
len = 2; |
1537 |
< |
Class<?> cc = comparableClassFor(k); |
1537 |
> |
Class<?> cc = comparableClassFor(k.getClass()); |
1538 |
|
TreeNode<K,V> p = t.getTreeNode(h, k, t.root, cc); |
1539 |
|
if (p != null || !onlyIfPresent) { |
1540 |
|
V pv = (p == null) ? null : p.val; |
1632 |
|
try { |
1633 |
|
if (tabAt(tab, i) == f) { |
1634 |
|
len = 2; |
1635 |
< |
Class<?> cc = comparableClassFor(k); |
1635 |
> |
Class<?> cc = comparableClassFor(k.getClass()); |
1636 |
|
TreeNode<K,V> p = t.getTreeNode(h, k, t.root, cc); |
1637 |
|
val = (p == null) ? v : mf.apply(p.val, v); |
1638 |
|
if (val != null) { |
1731 |
|
try { |
1732 |
|
if (tabAt(tab, i) == f) { |
1733 |
|
validated = true; |
1734 |
< |
Class<?> cc = comparableClassFor(k); |
1734 |
> |
Class<?> cc = comparableClassFor(k.getClass()); |
1735 |
|
TreeNode<K,V> p = t.getTreeNode(h, k, |
1736 |
|
t.root, cc); |
1737 |
|
if (p != null) |