1568 |
|
void checkInvariants() { |
1569 |
|
// meta-assertions |
1570 |
|
// assert lock.isHeldByCurrentThread(); |
1571 |
< |
try { |
1572 |
< |
// Unlike ArrayDeque, we have a count field but no spare slot. |
1573 |
< |
// We prefer ArrayDeque's strategy (and the names of its fields!), |
1574 |
< |
// but our field layout is baked into the serial form, and so is |
1575 |
< |
// too annoying to change. |
1576 |
< |
// |
1577 |
< |
// putIndex == takeIndex must be disambiguated by checking count. |
1578 |
< |
int capacity = items.length; |
1579 |
< |
// assert capacity > 0; |
1580 |
< |
// assert takeIndex >= 0 && takeIndex < capacity; |
1581 |
< |
// assert putIndex >= 0 && putIndex < capacity; |
1582 |
< |
// assert count <= capacity; |
1583 |
< |
// assert takeIndex == putIndex || items[takeIndex] != null; |
1584 |
< |
// assert count == capacity || items[putIndex] == null; |
1585 |
< |
// assert takeIndex == putIndex || items[dec(putIndex, capacity)] != null; |
1586 |
< |
} catch (Throwable t) { |
1587 |
< |
System.err.printf("takeIndex=%d putIndex=%d count=%d capacity=%d%n", |
1588 |
< |
takeIndex, putIndex, count, items.length); |
1589 |
< |
System.err.printf("items=%s%n", |
1590 |
< |
Arrays.toString(items)); |
1591 |
< |
throw t; |
1571 |
> |
if (!invariantsSatisfied()) { |
1572 |
> |
String detail = String.format( |
1573 |
> |
"takeIndex=%d putIndex=%d count=%d capacity=%d items=%s", |
1574 |
> |
takeIndex, putIndex, count, items.length, |
1575 |
> |
Arrays.toString(items)); |
1576 |
> |
System.err.println(detail); |
1577 |
> |
throw new AssertionError(detail); |
1578 |
|
} |
1579 |
|
} |
1580 |
|
|
1581 |
+ |
private boolean invariantsSatisfied() { |
1582 |
+ |
// Unlike ArrayDeque, we have a count field but no spare slot. |
1583 |
+ |
// We prefer ArrayDeque's strategy (and the names of its fields!), |
1584 |
+ |
// but our field layout is baked into the serial form, and so is |
1585 |
+ |
// too annoying to change. |
1586 |
+ |
// |
1587 |
+ |
// putIndex == takeIndex must be disambiguated by checking count. |
1588 |
+ |
int capacity = items.length; |
1589 |
+ |
return capacity > 0 |
1590 |
+ |
&& items.getClass() == Object[].class |
1591 |
+ |
&& (takeIndex | putIndex | count) >= 0 |
1592 |
+ |
&& takeIndex < capacity |
1593 |
+ |
&& putIndex < capacity |
1594 |
+ |
&& count <= capacity |
1595 |
+ |
&& (putIndex - takeIndex - count) % capacity == 0 |
1596 |
+ |
&& (count == 0 || items[takeIndex] != null) |
1597 |
+ |
&& (count == capacity || items[putIndex] == null) |
1598 |
+ |
&& (count == 0 || items[dec(putIndex, capacity)] != null); |
1599 |
+ |
} |
1600 |
+ |
|
1601 |
|
/** |
1602 |
< |
* Deserializes this queue and then checks some invariants. |
1602 |
> |
* Reconstitutes this queue from a stream (that is, deserializes it). |
1603 |
|
* |
1604 |
< |
* @param s the input stream |
1604 |
> |
* @param s the stream |
1605 |
|
* @throws ClassNotFoundException if the class of a serialized object |
1606 |
|
* could not be found |
1607 |
|
* @throws java.io.InvalidObjectException if invariants are violated |
1613 |
|
// Read in items array and various fields |
1614 |
|
s.defaultReadObject(); |
1615 |
|
|
1616 |
< |
// Check invariants over count and index fields. Note that |
1611 |
< |
// if putIndex==takeIndex, count can be either 0 or items.length. |
1612 |
< |
if (items.length == 0 || |
1613 |
< |
takeIndex < 0 || takeIndex >= items.length || |
1614 |
< |
putIndex < 0 || putIndex >= items.length || |
1615 |
< |
count < 0 || count > items.length || |
1616 |
< |
Math.floorMod(putIndex - takeIndex, items.length) != |
1617 |
< |
Math.floorMod(count, items.length)) { |
1616 |
> |
if (!invariantsSatisfied()) |
1617 |
|
throw new java.io.InvalidObjectException("invariants violated"); |
1619 |
– |
} |
1618 |
|
} |
1619 |
|
} |