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