1 28 29 package org.dom4j.tree; 30 31 import java.io.IOException ; 32 import java.io.Serializable ; 33 import java.util.AbstractCollection ; 34 import java.util.AbstractMap ; 35 import java.util.AbstractSet ; 36 import java.util.Collection ; 37 import java.util.Enumeration ; 38 import java.util.Iterator ; 39 import java.util.Map ; 40 import java.util.NoSuchElementException ; 41 import java.util.Set ; 42 43 154 155 class ConcurrentReaderHashMap extends AbstractMap implements Map , Cloneable , 156 Serializable { 157 158 179 180 181 protected static class BarrierLock implements java.io.Serializable { 182 } 183 184 187 protected final BarrierLock barrierLock = new BarrierLock(); 188 189 192 193 protected transient Object lastWrite; 194 195 199 protected final void recordModification(Object x) { 200 synchronized (barrierLock) { 201 lastWrite = x; 202 } 203 } 204 205 209 protected final Entry[] getTableForReading() { 210 synchronized (barrierLock) { 211 return table; 212 } 213 } 214 215 219 public static int DEFAULT_INITIAL_CAPACITY = 32; 220 221 225 private static final int MINIMUM_CAPACITY = 4; 226 227 232 private static final int MAXIMUM_CAPACITY = 1 << 30; 233 234 238 239 public static final float DEFAULT_LOAD_FACTOR = 0.75f; 240 241 244 protected transient Entry[] table; 245 246 249 protected transient int count; 250 251 257 protected int threshold; 258 259 264 protected float loadFactor; 265 266 270 private int p2capacity(int initialCapacity) { 271 int cap = initialCapacity; 272 273 int result; 275 if (cap > MAXIMUM_CAPACITY || cap < 0) { 276 result = MAXIMUM_CAPACITY; 277 } else { 278 result = MINIMUM_CAPACITY; 279 while (result < cap) 280 result <<= 1; 281 } 282 return result; 283 } 284 285 290 private static int hash(Object x) { 291 int h = x.hashCode(); 292 return ((h << 7) - h + (h >>> 9) + (h >>> 17)); 296 } 297 298 301 protected boolean eq(Object x, Object y) { 302 return x == y || x.equals(y); 303 } 304 305 318 319 public ConcurrentReaderHashMap(int initialCapacity, float loadFactor) { 320 if (loadFactor <= 0) 321 throw new IllegalArgumentException ("Illegal Load factor: " 322 + loadFactor); 323 this.loadFactor = loadFactor; 324 325 int cap = p2capacity(initialCapacity); 326 327 table = new Entry[cap]; 328 threshold = (int) (cap * loadFactor); 329 } 330 331 340 341 public ConcurrentReaderHashMap(int initialCapacity) { 342 this(initialCapacity, DEFAULT_LOAD_FACTOR); 343 } 344 345 349 350 public ConcurrentReaderHashMap() { 351 this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR); 352 } 353 354 359 360 public ConcurrentReaderHashMap(Map t) { 361 this(Math.max((int) (t.size() / DEFAULT_LOAD_FACTOR) + 1, 16), 362 DEFAULT_LOAD_FACTOR); 363 putAll(t); 364 } 365 366 371 372 public synchronized int size() { 373 return count; 374 } 375 376 381 382 public synchronized boolean isEmpty() { 383 return count == 0; 384 } 385 386 398 399 public Object get(Object key) { 400 401 int hash = hash(key); 403 404 411 412 Entry[] tab = table; 413 int index = hash & (tab.length - 1); 414 Entry first = tab[index]; 415 Entry e = first; 416 417 for (;;) { 418 if (e == null) { 419 420 423 Entry[] reread = getTableForReading(); 424 if (tab == reread && first == tab[index]) 425 return null; 426 else { 427 tab = reread; 429 e = first = tab[index = hash & (tab.length - 1)]; 430 } 431 432 } 433 434 else if (e.hash == hash && eq(key, e.key)) { 435 Object value = e.value; 436 if (value != null) 437 return value; 438 439 445 synchronized (this) { 446 tab = table; 447 } 448 e = first = tab[index = hash & (tab.length - 1)]; 449 450 } else 451 e = e.next; 452 } 453 } 454 455 467 468 public boolean containsKey(Object key) { 469 return get(key) != null; 470 } 471 472 491 492 public Object put(Object key, Object value) { 493 if (value == null) 494 throw new NullPointerException (); 495 496 int hash = hash(key); 497 Entry[] tab = table; 498 int index = hash & (tab.length - 1); 499 Entry first = tab[index]; 500 Entry e; 501 502 for (e = first; e != null; e = e.next) 503 if (e.hash == hash && eq(key, e.key)) 504 break; 505 506 synchronized (this) { 507 if (tab == table) { 508 if (e == null) { 509 if (first == tab[index]) { 511 Entry newEntry = new Entry(hash, key, value, first); 513 tab[index] = newEntry; 514 if (++count >= threshold) 515 rehash(); 516 else 517 recordModification(newEntry); 518 return null; 519 } 520 } else { 521 Object oldValue = e.value; 522 if (first == tab[index] && oldValue != null) { 523 e.value = value; 524 return oldValue; 525 } 526 } 527 } 528 529 return sput(key, value, hash); 531 } 532 } 533 534 538 protected Object sput(Object key, Object value, int hash) { 539 540 Entry[] tab = table; 541 int index = hash & (tab.length - 1); 542 Entry first = tab[index]; 543 Entry e = first; 544 545 for (;;) { 546 if (e == null) { 547 Entry newEntry = new Entry(hash, key, value, first); 548 tab[index] = newEntry; 549 if (++count >= threshold) 550 rehash(); 551 else 552 recordModification(newEntry); 553 return null; 554 } else if (e.hash == hash && eq(key, e.key)) { 555 Object oldValue = e.value; 556 e.value = value; 557 return oldValue; 558 } else 559 e = e.next; 560 } 561 } 562 563 568 protected void rehash() { 569 Entry[] oldTable = table; 570 int oldCapacity = oldTable.length; 571 if (oldCapacity >= MAXIMUM_CAPACITY) { 572 threshold = Integer.MAX_VALUE; return; 574 } 575 576 int newCapacity = oldCapacity << 1; 577 int mask = newCapacity - 1; 578 threshold = (int) (newCapacity * loadFactor); 579 580 Entry[] newTable = new Entry[newCapacity]; 581 592 593 for (int i = 0; i < oldCapacity; i++) { 594 Entry e = oldTable[i]; 597 598 if (e != null) { 599 int idx = e.hash & mask; 600 Entry next = e.next; 601 602 if (next == null) 604 newTable[idx] = e; 605 606 else { 607 Entry lastRun = e; 609 int lastIdx = idx; 610 for (Entry last = next; last != null; last = last.next) { 611 int k = last.hash & mask; 612 if (k != lastIdx) { 613 lastIdx = k; 614 lastRun = last; 615 } 616 } 617 newTable[lastIdx] = lastRun; 618 619 for (Entry p = e; p != lastRun; p = p.next) { 621 int k = p.hash & mask; 622 newTable[k] = new Entry(p.hash, p.key, p.value, 623 newTable[k]); 624 } 625 } 626 } 627 } 628 629 table = newTable; 630 recordModification(newTable); 631 } 632 633 644 645 public Object remove(Object key) { 646 653 654 int hash = hash(key); 655 Entry[] tab = table; 656 int index = hash & (tab.length - 1); 657 Entry first = tab[index]; 658 Entry e = first; 659 660 for (e = first; e != null; e = e.next) 661 if (e.hash == hash && eq(key, e.key)) 662 break; 663 664 synchronized (this) { 665 if (tab == table) { 666 if (e == null) { 667 if (first == tab[index]) 668 return null; 669 } else { 670 Object oldValue = e.value; 671 if (first == tab[index] && oldValue != null) { 672 e.value = null; 673 count--; 674 675 Entry head = e.next; 676 for (Entry p = first; p != e; p = p.next) 677 head = new Entry(p.hash, p.key, p.value, head); 678 679 tab[index] = head; 680 recordModification(head); 681 return oldValue; 682 } 683 } 684 } 685 686 return sremove(key, hash); 688 } 689 } 690 691 695 696 protected Object sremove(Object key, int hash) { 697 Entry[] tab = table; 698 int index = hash & (tab.length - 1); 699 Entry first = tab[index]; 700 701 for (Entry e = first; e != null; e = e.next) { 702 if (e.hash == hash && eq(key, e.key)) { 703 Object oldValue = e.value; 704 e.value = null; 705 count--; 706 Entry head = e.next; 707 for (Entry p = first; p != e; p = p.next) 708 head = new Entry(p.hash, p.key, p.value, head); 709 710 tab[index] = head; 711 recordModification(head); 712 return oldValue; 713 } 714 } 715 return null; 716 } 717 718 730 731 public boolean containsValue(Object value) { 732 if (value == null) 733 throw new NullPointerException (); 734 735 Entry tab[] = getTableForReading(); 736 737 for (int i = 0; i < tab.length; ++i) { 738 for (Entry e = tab[i]; e != null; e = e.next) 739 if (value.equals(e.value)) 740 return true; 741 } 742 743 return false; 744 } 745 746 765 766 public boolean contains(Object value) { 767 return containsValue(value); 768 } 769 770 779 780 public synchronized void putAll(Map t) { 781 int n = t.size(); 782 if (n == 0) 783 return; 784 785 while (n >= threshold) 789 rehash(); 790 791 for (Iterator it = t.entrySet().iterator(); it.hasNext();) { 792 Map.Entry entry = (Map.Entry ) it.next(); 793 Object key = entry.getKey(); 794 Object value = entry.getValue(); 795 put(key, value); 796 } 797 } 798 799 802 public synchronized void clear() { 803 Entry tab[] = table; 804 for (int i = 0; i < tab.length; ++i) { 805 806 for (Entry e = tab[i]; e != null; e = e.next) 809 e.value = null; 810 811 tab[i] = null; 812 } 813 count = 0; 814 recordModification(tab); 815 } 816 817 823 824 public synchronized Object clone() { 825 try { 826 ConcurrentReaderHashMap t = (ConcurrentReaderHashMap) super.clone(); 827 828 t.keySet = null; 829 t.entrySet = null; 830 t.values = null; 831 832 Entry[] tab = table; 833 t.table = new Entry[tab.length]; 834 Entry[] ttab = t.table; 835 836 for (int i = 0; i < tab.length; ++i) { 837 Entry first = null; 838 for (Entry e = tab[i]; e != null; e = e.next) 839 first = new Entry(e.hash, e.key, e.value, first); 840 ttab[i] = first; 841 } 842 843 return t; 844 } catch (CloneNotSupportedException e) { 845 throw new InternalError (); 847 } 848 } 849 850 852 protected transient Set keySet = null; 853 854 protected transient Set entrySet = null; 855 856 protected transient Collection values = null; 857 858 869 870 public Set keySet() { 871 Set ks = keySet; 872 return (ks != null) ? ks : (keySet = new KeySet()); 873 } 874 875 private class KeySet extends AbstractSet { 876 public Iterator iterator() { 877 return new KeyIterator(); 878 } 879 880 public int size() { 881 return ConcurrentReaderHashMap.this.size(); 882 } 883 884 public boolean contains(Object o) { 885 return ConcurrentReaderHashMap.this.containsKey(o); 886 } 887 888 public boolean remove(Object o) { 889 return ConcurrentReaderHashMap.this.remove(o) != null; 890 } 891 892 public void clear() { 893 ConcurrentReaderHashMap.this.clear(); 894 } 895 } 896 897 909 910 public Collection values() { 911 Collection vs = values; 912 return (vs != null) ? vs : (values = new Values()); 913 } 914 915 private class Values extends AbstractCollection { 916 public Iterator iterator() { 917 return new ValueIterator(); 918 } 919 920 public int size() { 921 return ConcurrentReaderHashMap.this.size(); 922 } 923 924 public boolean contains(Object o) { 925 return ConcurrentReaderHashMap.this.containsValue(o); 926 } 927 928 public void clear() { 929 ConcurrentReaderHashMap.this.clear(); 930 } 931 } 932 933 946 947 public Set entrySet() { 948 Set es = entrySet; 949 return (es != null) ? es : (entrySet = new EntrySet()); 950 } 951 952 private class EntrySet extends AbstractSet { 953 public Iterator iterator() { 954 return new HashIterator(); 955 } 956 957 public boolean contains(Object o) { 958 if (!(o instanceof Map.Entry )) 959 return false; 960 Map.Entry entry = (Map.Entry ) o; 961 Object v = ConcurrentReaderHashMap.this.get(entry.getKey()); 962 return v != null && v.equals(entry.getValue()); 963 } 964 965 public boolean remove(Object o) { 966 if (!(o instanceof Map.Entry )) 967 return false; 968 return ConcurrentReaderHashMap.this 969 .findAndRemoveEntry((Map.Entry ) o); 970 } 971 972 public int size() { 973 return ConcurrentReaderHashMap.this.size(); 974 } 975 976 public void clear() { 977 ConcurrentReaderHashMap.this.clear(); 978 } 979 } 980 981 984 protected synchronized boolean findAndRemoveEntry(Map.Entry entry) { 985 Object key = entry.getKey(); 986 Object v = get(key); 987 if (v != null && v.equals(entry.getValue())) { 988 remove(key); 989 return true; 990 } else 991 return false; 992 } 993 994 1003 public Enumeration keys() { 1004 return new KeyIterator(); 1005 } 1006 1007 1017 1018 public Enumeration elements() { 1019 return new ValueIterator(); 1020 } 1021 1022 1025 1026 protected static class Entry implements Map.Entry { 1027 1028 1033 1034 protected final int hash; 1035 1036 protected final Object key; 1037 1038 protected final Entry next; 1039 1040 protected volatile Object value; 1041 1042 Entry(int hash, Object key, Object value, Entry next) { 1043 this.hash = hash; 1044 this.key = key; 1045 this.next = next; 1046 this.value = value; 1047 } 1048 1049 1051 public Object getKey() { 1052 return key; 1053 } 1054 1055 1067 public Object getValue() { 1068 return value; 1069 } 1070 1071 1092 1093 public Object setValue(Object value) { 1094 if (value == null) 1095 throw new NullPointerException (); 1096 Object oldValue = this.value; 1097 this.value = value; 1098 return oldValue; 1099 } 1100 1101 public boolean equals(Object o) { 1102 if (!(o instanceof Map.Entry )) 1103 return false; 1104 Map.Entry e = (Map.Entry ) o; 1105 return (key.equals(e.getKey()) && value.equals(e.getValue())); 1106 } 1107 1108 public int hashCode() { 1109 return key.hashCode() ^ value.hashCode(); 1110 } 1111 1112 public String toString() { 1113 return key + "=" + value; 1114 } 1115 1116 } 1117 1118 protected class HashIterator implements Iterator , Enumeration { 1119 protected final Entry[] tab; 1121 protected int index; 1123 protected Entry entry = null; 1125 protected Object currentKey; 1127 protected Object currentValue; 1129 protected Entry lastReturned = null; 1131 protected HashIterator() { 1132 tab = ConcurrentReaderHashMap.this.getTableForReading(); 1133 index = tab.length - 1; 1134 } 1135 1136 public boolean hasMoreElements() { 1137 return hasNext(); 1138 } 1139 1140 public Object nextElement() { 1141 return next(); 1142 } 1143 1144 public boolean hasNext() { 1145 1146 1152 1153 for (;;) { 1154 if (entry != null) { 1155 Object v = entry.value; 1156 if (v != null) { 1157 currentKey = entry.key; 1158 currentValue = v; 1159 return true; 1160 } else 1161 entry = entry.next; 1162 } 1163 1164 while (entry == null && index >= 0) 1165 entry = tab[index--]; 1166 1167 if (entry == null) { 1168 currentKey = currentValue = null; 1169 return false; 1170 } 1171 } 1172 } 1173 1174 protected Object returnValueOfNext() { 1175 return entry; 1176 } 1177 1178 public Object next() { 1179 if (currentKey == null && !hasNext()) 1180 throw new NoSuchElementException (); 1181 1182 Object result = returnValueOfNext(); 1183 lastReturned = entry; 1184 currentKey = currentValue = null; 1185 entry = entry.next; 1186 return result; 1187 } 1188 1189 public void remove() { 1190 if (lastReturned == null) 1191 throw new IllegalStateException (); 1192 ConcurrentReaderHashMap.this.remove(lastReturned.key); 1193 lastReturned = null; 1194 } 1195 1196 } 1197 1198 protected class KeyIterator extends HashIterator { 1199 protected Object returnValueOfNext() { 1200 return currentKey; 1201 } 1202 } 1203 1204 protected class ValueIterator extends HashIterator { 1205 protected Object returnValueOfNext() { 1206 return currentValue; 1207 } 1208 } 1209 1210 1222 1223 private synchronized void writeObject(java.io.ObjectOutputStream s) 1224 throws IOException { 1225 s.defaultWriteObject(); 1227 1228 s.writeInt(table.length); 1230 1231 s.writeInt(count); 1233 1234 for (int index = table.length - 1; index >= 0; index--) { 1236 Entry entry = table[index]; 1237 1238 while (entry != null) { 1239 s.writeObject(entry.key); 1240 s.writeObject(entry.value); 1241 entry = entry.next; 1242 } 1243 } 1244 } 1245 1246 1250 private synchronized void readObject(java.io.ObjectInputStream s) 1251 throws IOException , ClassNotFoundException { 1252 s.defaultReadObject(); 1254 1255 int numBuckets = s.readInt(); 1257 table = new Entry[numBuckets]; 1258 1259 int size = s.readInt(); 1261 1262 for (int i = 0; i < size; i++) { 1264 Object key = s.readObject(); 1265 Object value = s.readObject(); 1266 put(key, value); 1267 } 1268 } 1269 1270 1273 1274 public synchronized int capacity() { 1275 return table.length; 1276 } 1277 1278 1281 public float loadFactor() { 1282 return loadFactor; 1283 } 1284} 1285 | Popular Tags |