23 */
24
25 /*
26 * This file is available under and governed by the GNU General Public
27 * License version 2 only, as published by the Free Software Foundation.
28 * However, the following notice accompanied the original version of this
29 * file:
30 *
31 * Written by Doug Lea with assistance from members of JCP JSR-166
32 * Expert Group and released to the public domain, as explained at
33 * http://creativecommons.org/licenses/publicdomain
34 */
35
36 package java.util.concurrent;
37 import java.util.concurrent.locks.*;
38 import java.util.*;
39 import java.io.Serializable;
40 import java.io.IOException;
41 import java.io.ObjectInputStream;
42 import java.io.ObjectOutputStream;
43
44 /**
45 * A hash table supporting full concurrency of retrievals and
46 * adjustable expected concurrency for updates. This class obeys the
47 * same functional specification as {@link java.util.Hashtable}, and
48 * includes versions of methods corresponding to each method of
49 * <tt>Hashtable</tt>. However, even though all operations are
50 * thread-safe, retrieval operations do <em>not</em> entail locking,
51 * and there is <em>not</em> any support for locking the entire table
52 * in a way that prevents all access. This class is fully
53 * interoperable with <tt>Hashtable</tt> in programs that rely on its
54 * thread safety but not on its synchronization details.
55 *
56 * <p> Retrieval operations (including <tt>get</tt>) generally do not
57 * block, so may overlap with update operations (including
58 * <tt>put</tt> and <tt>remove</tt>). Retrievals reflect the results
59 * of the most recently <em>completed</em> update operations holding
60 * upon their onset. For aggregate operations such as <tt>putAll</tt>
61 * and <tt>clear</tt>, concurrent retrievals may reflect insertion or
62 * removal of only some entries. Similarly, Iterators and
1430 s.writeObject(e.key);
1431 s.writeObject(e.value);
1432 }
1433 }
1434 } finally {
1435 seg.unlock();
1436 }
1437 }
1438 s.writeObject(null);
1439 s.writeObject(null);
1440 }
1441
1442 /**
1443 * Reconstitute the <tt>ConcurrentHashMap</tt> instance from a
1444 * stream (i.e., deserialize it).
1445 * @param s the stream
1446 */
1447 @SuppressWarnings("unchecked")
1448 private void readObject(java.io.ObjectInputStream s)
1449 throws IOException, ClassNotFoundException {
1450 s.defaultReadObject();
1451
1452 // Re-initialize segments to be minimally sized, and let grow.
1453 int cap = MIN_SEGMENT_TABLE_CAPACITY;
1454 final Segment<K,V>[] segments = this.segments;
1455 for (int k = 0; k < segments.length; ++k) {
1456 Segment<K,V> seg = segments[k];
1457 if (seg != null) {
1458 seg.threshold = (int)(cap * seg.loadFactor);
1459 seg.table = (HashEntry<K,V>[]) new HashEntry[cap];
1460 }
1461 }
1462
1463 // Read the keys and values, and put the mappings in the table
1464 for (;;) {
1465 K key = (K) s.readObject();
1466 V value = (V) s.readObject();
1467 if (key == null)
1468 break;
1469 put(key, value);
1470 }
1471 }
1472
1473 // Unsafe mechanics
1474 private static final sun.misc.Unsafe UNSAFE;
1475 private static final long SBASE;
1476 private static final int SSHIFT;
1477 private static final long TBASE;
1478 private static final int TSHIFT;
1479
1480 static {
1481 int ss, ts;
1482 try {
1483 UNSAFE = sun.misc.Unsafe.getUnsafe();
1484 Class tc = HashEntry[].class;
1485 Class sc = Segment[].class;
1486 TBASE = UNSAFE.arrayBaseOffset(tc);
1487 SBASE = UNSAFE.arrayBaseOffset(sc);
1488 ts = UNSAFE.arrayIndexScale(tc);
1489 ss = UNSAFE.arrayIndexScale(sc);
1490 } catch (Exception e) {
1491 throw new Error(e);
1492 }
1493 if ((ss & (ss-1)) != 0 || (ts & (ts-1)) != 0)
1494 throw new Error("data type scale not a power of two");
1495 SSHIFT = 31 - Integer.numberOfLeadingZeros(ss);
1496 TSHIFT = 31 - Integer.numberOfLeadingZeros(ts);
1497 }
1498
1499 }
|
23 */
24
25 /*
26 * This file is available under and governed by the GNU General Public
27 * License version 2 only, as published by the Free Software Foundation.
28 * However, the following notice accompanied the original version of this
29 * file:
30 *
31 * Written by Doug Lea with assistance from members of JCP JSR-166
32 * Expert Group and released to the public domain, as explained at
33 * http://creativecommons.org/licenses/publicdomain
34 */
35
36 package java.util.concurrent;
37 import java.util.concurrent.locks.*;
38 import java.util.*;
39 import java.io.Serializable;
40 import java.io.IOException;
41 import java.io.ObjectInputStream;
42 import java.io.ObjectOutputStream;
43 import java.io.ObjectStreamField;
44
45 /**
46 * A hash table supporting full concurrency of retrievals and
47 * adjustable expected concurrency for updates. This class obeys the
48 * same functional specification as {@link java.util.Hashtable}, and
49 * includes versions of methods corresponding to each method of
50 * <tt>Hashtable</tt>. However, even though all operations are
51 * thread-safe, retrieval operations do <em>not</em> entail locking,
52 * and there is <em>not</em> any support for locking the entire table
53 * in a way that prevents all access. This class is fully
54 * interoperable with <tt>Hashtable</tt> in programs that rely on its
55 * thread safety but not on its synchronization details.
56 *
57 * <p> Retrieval operations (including <tt>get</tt>) generally do not
58 * block, so may overlap with update operations (including
59 * <tt>put</tt> and <tt>remove</tt>). Retrievals reflect the results
60 * of the most recently <em>completed</em> update operations holding
61 * upon their onset. For aggregate operations such as <tt>putAll</tt>
62 * and <tt>clear</tt>, concurrent retrievals may reflect insertion or
63 * removal of only some entries. Similarly, Iterators and
1431 s.writeObject(e.key);
1432 s.writeObject(e.value);
1433 }
1434 }
1435 } finally {
1436 seg.unlock();
1437 }
1438 }
1439 s.writeObject(null);
1440 s.writeObject(null);
1441 }
1442
1443 /**
1444 * Reconstitute the <tt>ConcurrentHashMap</tt> instance from a
1445 * stream (i.e., deserialize it).
1446 * @param s the stream
1447 */
1448 @SuppressWarnings("unchecked")
1449 private void readObject(java.io.ObjectInputStream s)
1450 throws IOException, ClassNotFoundException {
1451 // Don't call defaultReadObject()
1452 ObjectInputStream.GetField oisFields = s.readFields();
1453 final Segment<K,V>[] oisSegments = (Segment<K,V>[])oisFields.get("segments", null);
1454
1455 final int ssize = oisSegments.length;
1456 if (ssize < 1 || ssize > MAX_SEGMENTS
1457 || (ssize & (ssize-1)) != 0 ) // ssize not power of two
1458 throw new java.io.InvalidObjectException("Bad number of segments:"
1459 + ssize);
1460 int sshift = 0, ssizeTmp = ssize;
1461 while (ssizeTmp > 1) {
1462 ++sshift;
1463 ssizeTmp >>>= 1;
1464 }
1465 UNSAFE.putIntVolatile(this, SEGSHIFT_OFFSET, 32 - sshift);
1466 UNSAFE.putIntVolatile(this, SEGMASK_OFFSET, ssize - 1);
1467 UNSAFE.putObjectVolatile(this, SEGMENTS_OFFSET, oisSegments);
1468
1469 // Re-initialize segments to be minimally sized, and let grow.
1470 int cap = MIN_SEGMENT_TABLE_CAPACITY;
1471 final Segment<K,V>[] segments = this.segments;
1472 for (int k = 0; k < segments.length; ++k) {
1473 Segment<K,V> seg = segments[k];
1474 if (seg != null) {
1475 seg.threshold = (int)(cap * seg.loadFactor);
1476 seg.table = (HashEntry<K,V>[]) new HashEntry[cap];
1477 }
1478 }
1479
1480 // Read the keys and values, and put the mappings in the table
1481 for (;;) {
1482 K key = (K) s.readObject();
1483 V value = (V) s.readObject();
1484 if (key == null)
1485 break;
1486 put(key, value);
1487 }
1488 }
1489
1490 // Unsafe mechanics
1491 private static final sun.misc.Unsafe UNSAFE;
1492 private static final long SBASE;
1493 private static final int SSHIFT;
1494 private static final long TBASE;
1495 private static final int TSHIFT;
1496 private static final long SEGSHIFT_OFFSET;
1497 private static final long SEGMASK_OFFSET;
1498 private static final long SEGMENTS_OFFSET;
1499
1500 static {
1501 int ss, ts;
1502 try {
1503 UNSAFE = sun.misc.Unsafe.getUnsafe();
1504 Class tc = HashEntry[].class;
1505 Class sc = Segment[].class;
1506 TBASE = UNSAFE.arrayBaseOffset(tc);
1507 SBASE = UNSAFE.arrayBaseOffset(sc);
1508 ts = UNSAFE.arrayIndexScale(tc);
1509 ss = UNSAFE.arrayIndexScale(sc);
1510 SEGSHIFT_OFFSET = UNSAFE.objectFieldOffset(
1511 ConcurrentHashMap.class.getDeclaredField("segmentShift"));
1512 SEGMASK_OFFSET = UNSAFE.objectFieldOffset(
1513 ConcurrentHashMap.class.getDeclaredField("segmentMask"));
1514 SEGMENTS_OFFSET = UNSAFE.objectFieldOffset(
1515 ConcurrentHashMap.class.getDeclaredField("segments"));
1516 } catch (Exception e) {
1517 throw new Error(e);
1518 }
1519 if ((ss & (ss-1)) != 0 || (ts & (ts-1)) != 0)
1520 throw new Error("data type scale not a power of two");
1521 SSHIFT = 31 - Integer.numberOfLeadingZeros(ss);
1522 TSHIFT = 31 - Integer.numberOfLeadingZeros(ts);
1523 }
1524
1525 }
|