1 6 7 package org.apache.beehive.netui.util.internal.concurrent; 8 9 import java.util.*; 10 import java.io.Serializable ; 11 import java.io.IOException ; 12 import java.io.ObjectInputStream ; 13 import java.io.ObjectOutputStream ; 14 15 73 public class InternalConcurrentHashMap extends AbstractMap 74 implements Map, Serializable { 75 private static final long serialVersionUID = 7249069246763182397L; 76 77 81 82 83 84 88 static int DEFAULT_INITIAL_CAPACITY = 16; 89 90 96 static final int MAXIMUM_CAPACITY = 1 << 30; 97 98 102 static final float DEFAULT_LOAD_FACTOR = 0.75f; 103 104 107 static final int DEFAULT_SEGMENTS = 16; 108 109 113 static final int MAX_SEGMENTS = 1 << 16; 115 121 static final int RETRIES_BEFORE_LOCK = 2; 122 123 124 125 129 final int segmentMask; 130 131 134 final int segmentShift; 135 136 139 final Segment[] segments; 140 141 transient Set keySet; 142 transient Set entrySet; 143 transient Collection values; 144 145 146 147 153 static int hash(Object x) { 154 int h = x.hashCode(); 155 h += ~(h << 9); 156 h ^= (h >>> 14); 157 h += (h << 4); 158 h ^= (h >>> 10); 159 return h; 160 } 161 162 167 final Segment segmentFor(int hash) { 168 return (Segment) segments[(hash >>> segmentShift) & segmentMask]; 169 } 170 171 172 173 185 static final class HashEntry { 186 final Object key; 187 final int hash; 188 volatile Object value; 189 final HashEntry next; 190 191 HashEntry(Object key, int hash, HashEntry next, Object value) { 192 this.key = key; 193 this.hash = hash; 194 this.next = next; 195 this.value = value; 196 } 197 } 198 199 204 static final class Segment extends ReentrantLock implements Serializable { 205 241 242 private static final long serialVersionUID = 2249069246763182397L; 243 244 247 transient volatile int count; 248 249 257 transient int modCount; 258 259 264 transient int threshold; 265 266 270 transient volatile HashEntry[] table; 271 272 278 final float loadFactor; 279 280 Segment(int initialCapacity, float lf) { 281 loadFactor = lf; 282 setTable(new HashEntry[initialCapacity]); 283 } 284 285 289 void setTable(HashEntry[] newTable) { 290 threshold = (int)(newTable.length * loadFactor); 291 table = newTable; 292 } 293 294 297 HashEntry getFirst(int hash) { 298 HashEntry[] tab = table; 299 return (HashEntry) tab[hash & (tab.length - 1)]; 300 } 301 302 309 Object readValueUnderLock(HashEntry e) { 310 lock(); 311 try { 312 return e.value; 313 } finally { 314 unlock(); 315 } 316 } 317 318 319 320 Object get(Object key, int hash) { 321 if (count != 0) { HashEntry e = getFirst(hash); 323 while (e != null) { 324 if (e.hash == hash && key.equals(e.key)) { 325 Object v = e.value; 326 if (v != null) 327 return v; 328 return readValueUnderLock(e); } 330 e = e.next; 331 } 332 } 333 return null; 334 } 335 336 boolean containsKey(Object key, int hash) { 337 if (count != 0) { HashEntry e = getFirst(hash); 339 while (e != null) { 340 if (e.hash == hash && key.equals(e.key)) 341 return true; 342 e = e.next; 343 } 344 } 345 return false; 346 } 347 348 boolean containsValue(Object value) { 349 if (count != 0) { HashEntry[] tab = table; 351 int len = tab.length; 352 for (int i = 0 ; i < len; i++) { 353 for (HashEntry e = (HashEntry)tab[i]; 354 e != null ; 355 e = e.next) { 356 Object v = e.value; 357 if (v == null) v = readValueUnderLock(e); 359 if (value.equals(v)) 360 return true; 361 } 362 } 363 } 364 return false; 365 } 366 367 boolean replace(Object key, int hash, Object oldValue, Object newValue) { 368 lock(); 369 try { 370 HashEntry e = getFirst(hash); 371 while (e != null && (e.hash != hash || !key.equals(e.key))) 372 e = e.next; 373 374 boolean replaced = false; 375 if (e != null && oldValue.equals(e.value)) { 376 replaced = true; 377 e.value = newValue; 378 } 379 return replaced; 380 } finally { 381 unlock(); 382 } 383 } 384 385 Object replace(Object key, int hash, Object newValue) { 386 lock(); 387 try { 388 HashEntry e = getFirst(hash); 389 while (e != null && (e.hash != hash || !key.equals(e.key))) 390 e = e.next; 391 392 Object oldValue = null; 393 if (e != null) { 394 oldValue = e.value; 395 e.value = newValue; 396 } 397 return oldValue; 398 } finally { 399 unlock(); 400 } 401 } 402 403 404 Object put(Object key, int hash, Object value, boolean onlyIfAbsent) { 405 lock(); 406 try { 407 int c = count; 408 if (c++ > threshold) rehash(); 410 HashEntry[] tab = table; 411 int index = hash & (tab.length - 1); 412 HashEntry first = (HashEntry) tab[index]; 413 HashEntry e = first; 414 while (e != null && (e.hash != hash || !key.equals(e.key))) 415 e = e.next; 416 417 Object oldValue; 418 if (e != null) { 419 oldValue = e.value; 420 if (!onlyIfAbsent) 421 e.value = value; 422 } 423 else { 424 oldValue = null; 425 ++modCount; 426 tab[index] = new HashEntry(key, hash, first, value); 427 count = c; } 429 return oldValue; 430 } finally { 431 unlock(); 432 } 433 } 434 435 void rehash() { 436 HashEntry[] oldTable = table; 437 int oldCapacity = oldTable.length; 438 if (oldCapacity >= MAXIMUM_CAPACITY) 439 return; 440 441 454 455 HashEntry[] newTable = new HashEntry[oldCapacity << 1]; 456 threshold = (int)(newTable.length * loadFactor); 457 int sizeMask = newTable.length - 1; 458 for (int i = 0; i < oldCapacity ; i++) { 459 HashEntry e = (HashEntry)oldTable[i]; 462 463 if (e != null) { 464 HashEntry next = e.next; 465 int idx = e.hash & sizeMask; 466 467 if (next == null) 469 newTable[idx] = e; 470 471 else { 472 HashEntry lastRun = e; 474 int lastIdx = idx; 475 for (HashEntry last = next; 476 last != null; 477 last = last.next) { 478 int k = last.hash & sizeMask; 479 if (k != lastIdx) { 480 lastIdx = k; 481 lastRun = last; 482 } 483 } 484 newTable[lastIdx] = lastRun; 485 486 for (HashEntry p = e; p != lastRun; p = p.next) { 488 int k = p.hash & sizeMask; 489 HashEntry n = (HashEntry)newTable[k]; 490 newTable[k] = new HashEntry(p.key, p.hash, 491 n, p.value); 492 } 493 } 494 } 495 } 496 table = newTable; 497 } 498 499 502 Object remove(Object key, int hash, Object value) { 503 lock(); 504 try { 505 int c = count - 1; 506 HashEntry[] tab = table; 507 int index = hash & (tab.length - 1); 508 HashEntry first = (HashEntry)tab[index]; 509 HashEntry e = first; 510 while (e != null && (e.hash != hash || !key.equals(e.key))) 511 e = e.next; 512 513 Object oldValue = null; 514 if (e != null) { 515 Object v = e.value; 516 if (value == null || value.equals(v)) { 517 oldValue = v; 518 ++modCount; 522 HashEntry newFirst = e.next; 523 for (HashEntry p = first; p != e; p = p.next) 524 newFirst = new HashEntry(p.key, p.hash, 525 newFirst, p.value); 526 tab[index] = newFirst; 527 count = c; } 529 } 530 return oldValue; 531 } finally { 532 unlock(); 533 } 534 } 535 536 void clear() { 537 if (count != 0) { 538 lock(); 539 try { 540 HashEntry[] tab = table; 541 for (int i = 0; i < tab.length ; i++) 542 tab[i] = null; 543 ++modCount; 544 count = 0; } finally { 546 unlock(); 547 } 548 } 549 } 550 } 551 552 553 554 555 556 570 public InternalConcurrentHashMap(int initialCapacity, 571 float loadFactor, int concurrencyLevel) { 572 if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0) 573 throw new IllegalArgumentException (); 574 575 if (concurrencyLevel > MAX_SEGMENTS) 576 concurrencyLevel = MAX_SEGMENTS; 577 578 int sshift = 0; 580 int ssize = 1; 581 while (ssize < concurrencyLevel) { 582 ++sshift; 583 ssize <<= 1; 584 } 585 segmentShift = 32 - sshift; 586 segmentMask = ssize - 1; 587 this.segments = new Segment[ssize]; 588 589 if (initialCapacity > MAXIMUM_CAPACITY) 590 initialCapacity = MAXIMUM_CAPACITY; 591 int c = initialCapacity / ssize; 592 if (c * ssize < initialCapacity) 593 ++c; 594 int cap = 1; 595 while (cap < c) 596 cap <<= 1; 597 598 for (int i = 0; i < this.segments.length; ++i) 599 this.segments[i] = new Segment(cap, loadFactor); 600 } 601 602 613 public InternalConcurrentHashMap(int initialCapacity, float loadFactor) { 614 this(initialCapacity, loadFactor, DEFAULT_SEGMENTS); 615 } 616 617 626 public InternalConcurrentHashMap(int initialCapacity) { 627 this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_SEGMENTS); 628 } 629 630 634 public InternalConcurrentHashMap() { 635 this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_SEGMENTS); 636 } 637 638 645 public InternalConcurrentHashMap(Map t) { 646 this(Math.max((int) (t.size() / DEFAULT_LOAD_FACTOR) + 1, 647 16), 648 DEFAULT_LOAD_FACTOR, DEFAULT_SEGMENTS); 649 putAll(t); 650 } 651 652 public boolean isEmpty() { 654 final Segment[] segments = this.segments; 655 664 int[] mc = new int[segments.length]; 665 int mcsum = 0; 666 for (int i = 0; i < segments.length; ++i) { 667 if (segments[i].count != 0) 668 return false; 669 else 670 mcsum += mc[i] = segments[i].modCount; 671 } 672 if (mcsum != 0) { 676 for (int i = 0; i < segments.length; ++i) { 677 if (segments[i].count != 0 || 678 mc[i] != segments[i].modCount) 679 return false; 680 } 681 } 682 return true; 683 } 684 685 public int size() { 687 final Segment[] segments = this.segments; 688 long sum = 0; 689 long check = 0; 690 int[] mc = new int[segments.length]; 691 for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) { 694 check = 0; 695 sum = 0; 696 int mcsum = 0; 697 for (int i = 0; i < segments.length; ++i) { 698 sum += segments[i].count; 699 mcsum += mc[i] = segments[i].modCount; 700 } 701 if (mcsum != 0) { 702 for (int i = 0; i < segments.length; ++i) { 703 check += segments[i].count; 704 if (mc[i] != segments[i].modCount) { 705 check = -1; break; 707 } 708 } 709 } 710 if (check == sum) 711 break; 712 } 713 if (check != sum) { sum = 0; 715 for (int i = 0; i < segments.length; ++i) 716 segments[i].lock(); 717 for (int i = 0; i < segments.length; ++i) 718 sum += segments[i].count; 719 for (int i = 0; i < segments.length; ++i) 720 segments[i].unlock(); 721 } 722 if (sum > Integer.MAX_VALUE) 723 return Integer.MAX_VALUE; 724 else 725 return (int)sum; 726 } 727 728 729 739 public Object get(Object key) { 740 int hash = hash(key); return segmentFor(hash).get(key, hash); 742 } 743 744 754 public boolean containsKey(Object key) { 755 int hash = hash(key); return segmentFor(hash).containsKey(key, hash); 757 } 758 759 770 public boolean containsValue(Object value) { 771 if (value == null) 772 throw new NullPointerException (); 773 774 776 final Segment[] segments = this.segments; 777 int[] mc = new int[segments.length]; 778 779 for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) { 781 int sum = 0; 782 int mcsum = 0; 783 for (int i = 0; i < segments.length; ++i) { 784 int c = segments[i].count; 785 mcsum += mc[i] = segments[i].modCount; 786 if (segments[i].containsValue(value)) 787 return true; 788 } 789 boolean cleanSweep = true; 790 if (mcsum != 0) { 791 for (int i = 0; i < segments.length; ++i) { 792 int c = segments[i].count; 793 if (mc[i] != segments[i].modCount) { 794 cleanSweep = false; 795 break; 796 } 797 } 798 } 799 if (cleanSweep) 800 return false; 801 } 802 for (int i = 0; i < segments.length; ++i) 804 segments[i].lock(); 805 boolean found = false; 806 try { 807 for (int i = 0; i < segments.length; ++i) { 808 if (segments[i].containsValue(value)) { 809 found = true; 810 break; 811 } 812 } 813 } finally { 814 for (int i = 0; i < segments.length; ++i) 815 segments[i].unlock(); 816 } 817 return found; 818 } 819 820 835 public boolean contains(Object value) { 836 return containsValue(value); 837 } 838 839 854 public Object put(Object key, Object value) { 855 if (value == null) 856 throw new NullPointerException (); 857 int hash = hash(key); 858 return segmentFor(hash).put(key, hash, value, false); 859 } 860 861 879 public Object putIfAbsent(Object key, Object value) { 880 if (value == null) 881 throw new NullPointerException (); 882 int hash = hash(key); 883 return segmentFor(hash).put(key, hash, value, true); 884 } 885 886 887 895 public void putAll(Map t) { 896 for (Iterator it = t.entrySet().iterator(); it.hasNext(); ) { 897 Entry e = (Entry)it.next(); 898 put(e.getKey(), e.getValue()); 899 } 900 } 901 902 912 public Object remove(Object key) { 913 int hash = hash(key); 914 return segmentFor(hash).remove(key, hash, null); 915 } 916 917 933 public boolean remove(Object key, Object value) { 934 int hash = hash(key); 935 return segmentFor(hash).remove(key, hash, value) != null; 936 } 937 938 939 956 public boolean replace(Object key, Object oldValue, Object newValue) { 957 if (oldValue == null || newValue == null) 958 throw new NullPointerException (); 959 int hash = hash(key); 960 return segmentFor(hash).replace(key, hash, oldValue, newValue); 961 } 962 963 979 public Object replace(Object key, Object value) { 980 if (value == null) 981 throw new NullPointerException (); 982 int hash = hash(key); 983 return segmentFor(hash).replace(key, hash, value); 984 } 985 986 987 990 public void clear() { 991 for (int i = 0; i < segments.length; ++i) 992 segments[i].clear(); 993 } 994 995 996 1012 public Set keySet() { 1013 Set ks = keySet; 1014 return (ks != null) ? ks : (keySet = new KeySet()); 1015 } 1016 1017 1018 1034 public Collection values() { 1035 Collection vs = values; 1036 return (vs != null) ? vs : (values = new Values()); 1037 } 1038 1039 1040 1057 public Set entrySet() { 1058 Set es = entrySet; 1059 return (es != null) ? es : (entrySet = new EntrySet()); 1060 } 1061 1062 1063 1069 public Enumeration keys() { 1070 return new KeyIterator(); 1071 } 1072 1073 1079 public Enumeration elements() { 1080 return new ValueIterator(); 1081 } 1082 1083 1084 1085 abstract class HashIterator { 1086 int nextSegmentIndex; 1087 int nextTableIndex; 1088 HashEntry[] currentTable; 1089 HashEntry nextEntry; 1090 HashEntry lastReturned; 1091 1092 HashIterator() { 1093 nextSegmentIndex = segments.length - 1; 1094 nextTableIndex = -1; 1095 advance(); 1096 } 1097 1098 public boolean hasMoreElements() { return hasNext(); } 1099 1100 final void advance() { 1101 if (nextEntry != null && (nextEntry = nextEntry.next) != null) 1102 return; 1103 1104 while (nextTableIndex >= 0) { 1105 if ( (nextEntry = (HashEntry)currentTable[nextTableIndex--]) != null) 1106 return; 1107 } 1108 1109 while (nextSegmentIndex >= 0) { 1110 Segment seg = (Segment)segments[nextSegmentIndex--]; 1111 if (seg.count != 0) { 1112 currentTable = seg.table; 1113 for (int j = currentTable.length - 1; j >= 0; --j) { 1114 if ( (nextEntry = (HashEntry)currentTable[j]) != null) { 1115 nextTableIndex = j - 1; 1116 return; 1117 } 1118 } 1119 } 1120 } 1121 } 1122 1123 public boolean hasNext() { return nextEntry != null; } 1124 1125 HashEntry nextEntry() { 1126 if (nextEntry == null) 1127 throw new NoSuchElementException(); 1128 lastReturned = nextEntry; 1129 advance(); 1130 return lastReturned; 1131 } 1132 1133 public void remove() { 1134 if (lastReturned == null) 1135 throw new IllegalStateException (); 1136 InternalConcurrentHashMap.this.remove(lastReturned.key); 1137 lastReturned = null; 1138 } 1139 } 1140 1141 final class KeyIterator extends HashIterator implements Iterator, Enumeration { 1142 public Object next() { return super.nextEntry().key; } 1143 public Object nextElement() { return super.nextEntry().key; } 1144 } 1145 1146 final class ValueIterator extends HashIterator implements Iterator, Enumeration { 1147 public Object next() { return super.nextEntry().value; } 1148 public Object nextElement() { return super.nextEntry().value; } 1149 } 1150 1151 1152 1153 1159 final class EntryIterator extends HashIterator implements Map.Entry, Iterator { 1160 public Object next() { 1161 nextEntry(); 1162 return this; 1163 } 1164 1165 public Object getKey() { 1166 if (lastReturned == null) 1167 throw new IllegalStateException ("Entry was removed"); 1168 return lastReturned.key; 1169 } 1170 1171 public Object getValue() { 1172 if (lastReturned == null) 1173 throw new IllegalStateException ("Entry was removed"); 1174 return InternalConcurrentHashMap.this.get(lastReturned.key); 1175 } 1176 1177 public Object setValue(Object value) { 1178 if (lastReturned == null) 1179 throw new IllegalStateException ("Entry was removed"); 1180 return InternalConcurrentHashMap.this.put(lastReturned.key, value); 1181 } 1182 1183 public boolean equals(Object o) { 1184 if (lastReturned == null) 1186 return super.equals(o); 1187 if (!(o instanceof Map.Entry)) 1188 return false; 1189 Map.Entry e = (Map.Entry)o; 1190 return eq(getKey(), e.getKey()) && eq(getValue(), e.getValue()); 1191 } 1192 1193 public int hashCode() { 1194 if (lastReturned == null) 1196 return super.hashCode(); 1197 1198 Object k = getKey(); 1199 Object v = getValue(); 1200 return ((k == null) ? 0 : k.hashCode()) ^ 1201 ((v == null) ? 0 : v.hashCode()); 1202 } 1203 1204 public String toString() { 1205 if (lastReturned == null) 1207 return super.toString(); 1208 else 1209 return getKey() + "=" + getValue(); 1210 } 1211 1212 boolean eq(Object o1, Object o2) { 1213 return (o1 == null ? o2 == null : o1.equals(o2)); 1214 } 1215 1216 } 1217 1218 final class KeySet extends AbstractSet { 1219 public Iterator iterator() { 1220 return new KeyIterator(); 1221 } 1222 public int size() { 1223 return InternalConcurrentHashMap.this.size(); 1224 } 1225 public boolean contains(Object o) { 1226 return InternalConcurrentHashMap.this.containsKey(o); 1227 } 1228 public boolean remove(Object o) { 1229 return InternalConcurrentHashMap.this.remove(o) != null; 1230 } 1231 public void clear() { 1232 InternalConcurrentHashMap.this.clear(); 1233 } 1234 public Object [] toArray() { 1235 Collection c = new ArrayList(); 1236 for (Iterator i = iterator(); i.hasNext(); ) 1237 c.add(i.next()); 1238 return c.toArray(); 1239 } 1240 public Object [] toArray(Object [] a) { 1241 Collection c = new ArrayList(); 1242 for (Iterator i = iterator(); i.hasNext(); ) 1243 c.add(i.next()); 1244 return c.toArray(a); 1245 } 1246 } 1247 1248 final class Values extends AbstractCollection { 1249 public Iterator iterator() { 1250 return new ValueIterator(); 1251 } 1252 public int size() { 1253 return InternalConcurrentHashMap.this.size(); 1254 } 1255 public boolean contains(Object o) { 1256 return InternalConcurrentHashMap.this.containsValue(o); 1257 } 1258 public void clear() { 1259 InternalConcurrentHashMap.this.clear(); 1260 } 1261 public Object [] toArray() { 1262 Collection c = new ArrayList(); 1263 for (Iterator i = iterator(); i.hasNext(); ) 1264 c.add(i.next()); 1265 return c.toArray(); 1266 } 1267 public Object [] toArray(Object [] a) { 1268 Collection c = new ArrayList(); 1269 for (Iterator i = iterator(); i.hasNext(); ) 1270 c.add(i.next()); 1271 return c.toArray(a); 1272 } 1273 } 1274 1275 final class EntrySet extends AbstractSet { 1276 public Iterator iterator() { 1277 return new EntryIterator(); 1278 } 1279 public boolean contains(Object o) { 1280 if (!(o instanceof Map.Entry)) 1281 return false; 1282 Map.Entry e = (Map.Entry)o; 1283 Object v = InternalConcurrentHashMap.this.get(e.getKey()); 1284 return v != null && v.equals(e.getValue()); 1285 } 1286 public boolean remove(Object o) { 1287 if (!(o instanceof Map.Entry)) 1288 return false; 1289 Map.Entry e = (Map.Entry)o; 1290 return InternalConcurrentHashMap.this.remove(e.getKey(), e.getValue()); 1291 } 1292 public int size() { 1293 return InternalConcurrentHashMap.this.size(); 1294 } 1295 public void clear() { 1296 InternalConcurrentHashMap.this.clear(); 1297 } 1298 public Object [] toArray() { 1299 Collection c = new ArrayList(size()); 1302 for (Iterator i = iterator(); i.hasNext(); ) 1303 c.add(new SimpleEntry((Entry)i.next())); 1304 return c.toArray(); 1305 } 1306 public Object [] toArray(Object [] a) { 1307 Collection c = new ArrayList(size()); 1308 for (Iterator i = iterator(); i.hasNext(); ) 1309 c.add(new SimpleEntry((Entry)i.next())); 1310 return c.toArray(a); 1311 } 1312 1313 } 1314 1315 1319 static final class SimpleEntry implements Entry { 1320 Object key; 1321 Object value; 1322 1323 public SimpleEntry(Object key, Object value) { 1324 this.key = key; 1325 this.value = value; 1326 } 1327 1328 public SimpleEntry(Entry e) { 1329 this.key = e.getKey(); 1330 this.value = e.getValue(); 1331 } 1332 1333 public Object getKey() { 1334 return key; 1335 } 1336 1337 public Object getValue() { 1338 return value; 1339 } 1340 1341 public Object setValue(Object value) { 1342 Object oldValue = this.value; 1343 this.value = value; 1344 return oldValue; 1345 } 1346 1347 public boolean equals(Object o) { 1348 if (!(o instanceof Map.Entry)) 1349 return false; 1350 Map.Entry e = (Map.Entry)o; 1351 return eq(key, e.getKey()) && eq(value, e.getValue()); 1352 } 1353 1354 public int hashCode() { 1355 return ((key == null) ? 0 : key.hashCode()) ^ 1356 ((value == null) ? 0 : value.hashCode()); 1357 } 1358 1359 public String toString() { 1360 return key + "=" + value; 1361 } 1362 1363 static boolean eq(Object o1, Object o2) { 1364 return (o1 == null ? o2 == null : o1.equals(o2)); 1365 } 1366 } 1367 1368 1369 1370 1380 private void writeObject(java.io.ObjectOutputStream s) throws IOException { 1381 s.defaultWriteObject(); 1382 1383 for (int k = 0; k < segments.length; ++k) { 1384 Segment seg = (Segment)segments[k]; 1385 seg.lock(); 1386 try { 1387 HashEntry[] tab = seg.table; 1388 for (int i = 0; i < tab.length; ++i) { 1389 for (HashEntry e = (HashEntry)tab[i]; e != null; e = e.next) { 1390 s.writeObject(e.key); 1391 s.writeObject(e.value); 1392 } 1393 } 1394 } finally { 1395 seg.unlock(); 1396 } 1397 } 1398 s.writeObject(null); 1399 s.writeObject(null); 1400 } 1401 1402 1408 private void readObject(java.io.ObjectInputStream s) 1409 throws IOException , ClassNotFoundException { 1410 s.defaultReadObject(); 1411 1412 for (int i = 0; i < segments.length; ++i) { 1414 segments[i].setTable(new HashEntry[1]); 1415 } 1416 1417 for (;;) { 1419 Object key = (Object ) s.readObject(); 1420 Object value = (Object ) s.readObject(); 1421 if (key == null) 1422 break; 1423 put(key, value); 1424 } 1425 } 1426} 1427 1428 | Popular Tags |