32 * Expert Group and released to the public domain, as explained at |
32 * Expert Group and released to the public domain, as explained at |
33 * http://creativecommons.org/publicdomain/zero/1.0/ |
33 * http://creativecommons.org/publicdomain/zero/1.0/ |
34 */ |
34 */ |
35 |
35 |
36 package java.util.concurrent; |
36 package java.util.concurrent; |
|
37 import java.io.ObjectInputStream; |
37 import java.util.concurrent.locks.*; |
38 import java.util.concurrent.locks.*; |
38 import java.util.*; |
39 import java.util.*; |
39 import java.io.Serializable; |
40 import java.io.Serializable; |
40 |
41 |
41 /** |
42 /** |
1481 * @param s the stream |
1482 * @param s the stream |
1482 */ |
1483 */ |
1483 @SuppressWarnings("unchecked") |
1484 @SuppressWarnings("unchecked") |
1484 private void readObject(java.io.ObjectInputStream s) |
1485 private void readObject(java.io.ObjectInputStream s) |
1485 throws java.io.IOException, ClassNotFoundException { |
1486 throws java.io.IOException, ClassNotFoundException { |
1486 s.defaultReadObject(); |
1487 // Don't call defaultReadObject() |
|
1488 ObjectInputStream.GetField oisFields = s.readFields(); |
|
1489 final Segment<K,V>[] oisSegments = (Segment<K,V>[])oisFields.get("segments", null); |
|
1490 |
|
1491 final int ssize = oisSegments.length; |
|
1492 if (ssize < 1 || ssize > MAX_SEGMENTS |
|
1493 || (ssize & (ssize-1)) != 0 ) // ssize not power of two |
|
1494 throw new java.io.InvalidObjectException("Bad number of segments:" |
|
1495 + ssize); |
|
1496 int sshift = 0, ssizeTmp = ssize; |
|
1497 while (ssizeTmp > 1) { |
|
1498 ++sshift; |
|
1499 ssizeTmp >>>= 1; |
|
1500 } |
|
1501 UNSAFE.putIntVolatile(this, SEGSHIFT_OFFSET, 32 - sshift); |
|
1502 UNSAFE.putIntVolatile(this, SEGMASK_OFFSET, ssize - 1); |
|
1503 UNSAFE.putObjectVolatile(this, SEGMENTS_OFFSET, oisSegments); |
1487 |
1504 |
1488 // set hashMask |
1505 // set hashMask |
1489 UNSAFE.putIntVolatile(this, HASHSEED_OFFSET, |
1506 UNSAFE.putIntVolatile(this, HASHSEED_OFFSET, |
1490 sun.misc.Hashing.randomHashSeed(this)); |
1507 sun.misc.Hashing.randomHashSeed(this)); |
1491 |
1508 |
1515 private static final long SBASE; |
1532 private static final long SBASE; |
1516 private static final int SSHIFT; |
1533 private static final int SSHIFT; |
1517 private static final long TBASE; |
1534 private static final long TBASE; |
1518 private static final int TSHIFT; |
1535 private static final int TSHIFT; |
1519 private static final long HASHSEED_OFFSET; |
1536 private static final long HASHSEED_OFFSET; |
|
1537 private static final long SEGSHIFT_OFFSET; |
|
1538 private static final long SEGMASK_OFFSET; |
|
1539 private static final long SEGMENTS_OFFSET; |
1520 |
1540 |
1521 static { |
1541 static { |
1522 int ss, ts; |
1542 int ss, ts; |
1523 try { |
1543 try { |
1524 UNSAFE = sun.misc.Unsafe.getUnsafe(); |
1544 UNSAFE = sun.misc.Unsafe.getUnsafe(); |
1528 SBASE = UNSAFE.arrayBaseOffset(sc); |
1548 SBASE = UNSAFE.arrayBaseOffset(sc); |
1529 ts = UNSAFE.arrayIndexScale(tc); |
1549 ts = UNSAFE.arrayIndexScale(tc); |
1530 ss = UNSAFE.arrayIndexScale(sc); |
1550 ss = UNSAFE.arrayIndexScale(sc); |
1531 HASHSEED_OFFSET = UNSAFE.objectFieldOffset( |
1551 HASHSEED_OFFSET = UNSAFE.objectFieldOffset( |
1532 ConcurrentHashMap.class.getDeclaredField("hashSeed")); |
1552 ConcurrentHashMap.class.getDeclaredField("hashSeed")); |
|
1553 SEGSHIFT_OFFSET = UNSAFE.objectFieldOffset( |
|
1554 ConcurrentHashMap.class.getDeclaredField("segmentShift")); |
|
1555 SEGMASK_OFFSET = UNSAFE.objectFieldOffset( |
|
1556 ConcurrentHashMap.class.getDeclaredField("segmentMask")); |
|
1557 SEGMENTS_OFFSET = UNSAFE.objectFieldOffset( |
|
1558 ConcurrentHashMap.class.getDeclaredField("segments")); |
1533 } catch (Exception e) { |
1559 } catch (Exception e) { |
1534 throw new Error(e); |
1560 throw new Error(e); |
1535 } |
1561 } |
1536 if ((ss & (ss-1)) != 0 || (ts & (ts-1)) != 0) |
1562 if ((ss & (ss-1)) != 0 || (ts & (ts-1)) != 0) |
1537 throw new Error("data type scale not a power of two"); |
1563 throw new Error("data type scale not a power of two"); |