267 // reduce the number of virtual method invocations needed to access these |
267 // reduce the number of virtual method invocations needed to access these |
268 // values, which is especially costly when coding small buffers. |
268 // values, which is especially costly when coding small buffers. |
269 // |
269 // |
270 final $type$[] hb; // Non-null only for heap buffers |
270 final $type$[] hb; // Non-null only for heap buffers |
271 final int offset; |
271 final int offset; |
272 boolean isReadOnly; // Valid only for heap buffers |
272 boolean isReadOnly; |
273 |
273 |
274 // Creates a new buffer with the given mark, position, limit, capacity, |
274 // Creates a new buffer with the given mark, position, limit, capacity, |
275 // backing array, and array offset |
275 // backing array, and array offset |
276 // |
276 // |
277 $Type$Buffer(int mark, int pos, int lim, int cap, // package-private |
277 $Type$Buffer(int mark, int pos, int lim, int cap, // package-private |
1609 nativeByteOrder = |
1613 nativeByteOrder = |
1610 (bigEndian == (Bits.byteOrder() == ByteOrder.BIG_ENDIAN)); |
1614 (bigEndian == (Bits.byteOrder() == ByteOrder.BIG_ENDIAN)); |
1611 return this; |
1615 return this; |
1612 } |
1616 } |
1613 |
1617 |
|
1618 /** |
|
1619 * Returns the memory address, pointing to the byte at the given index, |
|
1620 * modulus the given unit size. |
|
1621 * |
|
1622 * <p> A return value greater than zero indicates the address of the byte at |
|
1623 * the index is misaligned for the unit size, and the value's quantity |
|
1624 * indicates how much the index should be rounded up or down to locate a |
|
1625 * byte at an aligned address. Otherwise, a value of {@code 0} indicates |
|
1626 * that the address of the byte at the index is aligned for the unit size. |
|
1627 * |
|
1628 * @apiNote |
|
1629 * This method may be utilized to determine if unit size bytes from an |
|
1630 * index can be accessed atomically, if supported by the native platform. |
|
1631 * |
|
1632 * @implNote |
|
1633 * This implementation throws {@code UnsupportedOperationException} for |
|
1634 * non-direct buffers when the given unit size is greater then {@code 8}. |
|
1635 * |
|
1636 * @param index |
|
1637 * The index to query for alignment offset, must be non-negative, no |
|
1638 * upper bounds check is performed |
|
1639 * |
|
1640 * @param unitSize |
|
1641 * The unit size in bytes, must be a power of {@code 2} |
|
1642 * |
|
1643 * @return The indexed byte's memory address modulus the unit size |
|
1644 * |
|
1645 * @throws IllegalArgumentException |
|
1646 * If the index is negative or the unit size is not a power of |
|
1647 * {@code 2} |
|
1648 * |
|
1649 * @throws UnsupportedOperationException |
|
1650 * If the native platform does not guarantee stable alignment offset |
|
1651 * values for the given unit size when managing the memory regions |
|
1652 * of buffers of the same kind as this buffer (direct or |
|
1653 * non-direct). For example, if garbage collection would result |
|
1654 * in the moving of a memory region covered by a non-direct buffer |
|
1655 * from one location to another and both locations have different |
|
1656 * alignment characteristics. |
|
1657 * |
|
1658 * @see #alignedSlice(int) |
|
1659 * @since 9 |
|
1660 */ |
|
1661 public final int alignmentOffset(int index, int unitSize) { |
|
1662 if (index < 0) |
|
1663 throw new IllegalArgumentException("Index less than zero: " + index); |
|
1664 if (unitSize < 1 || (unitSize & (unitSize - 1)) != 0) |
|
1665 throw new IllegalArgumentException("Unit size not a power of two: " + unitSize); |
|
1666 if (unitSize > 8 && !isDirect()) |
|
1667 throw new UnsupportedOperationException("Unit size unsupported for non-direct buffers: " + unitSize); |
|
1668 |
|
1669 return (int) ((address + index) % unitSize); |
|
1670 } |
|
1671 |
|
1672 /** |
|
1673 * Creates a new byte buffer whose content is a shared and aligned |
|
1674 * subsequence of this buffer's content. |
|
1675 * |
|
1676 * <p> The content of the new buffer will start at this buffer's current |
|
1677 * position rounded up to the index of the nearest aligned byte for the |
|
1678 * given unit size, and end at this buffer's limit rounded down to the index |
|
1679 * of the nearest aligned byte for the given unit size. |
|
1680 * If rounding results in out-of-bound values then the new buffer's capacity |
|
1681 * and limit will be zero. If rounding is within bounds the following |
|
1682 * expressions will be true for a new buffer {@code nb} and unit size |
|
1683 * {@code unitSize}: |
|
1684 * <pre>{@code |
|
1685 * nb.alignmentOffset(0, unitSize) == 0 |
|
1686 * nb.alignmentOffset(nb.limit(), unitSize) == 0 |
|
1687 * }</pre> |
|
1688 * |
|
1689 * <p> Changes to this buffer's content will be visible in the new |
|
1690 * buffer, and vice versa; the two buffers' position, limit, and mark |
|
1691 * values will be independent. |
|
1692 * |
|
1693 * <p> The new buffer's position will be zero, its capacity and its limit |
|
1694 * will be the number of bytes remaining in this buffer or fewer subject to |
|
1695 * alignment, its mark will be undefined, and its byte order will be |
|
1696 * {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}. |
|
1697 * |
|
1698 * The new buffer will be direct if, and only if, this buffer is direct, and |
|
1699 * it will be read-only if, and only if, this buffer is read-only. </p> |
|
1700 * |
|
1701 * @apiNote |
|
1702 * This method may be utilized to create a new buffer where unit size bytes |
|
1703 * from index, that is a multiple of the unit size, may be accessed |
|
1704 * atomically, if supported by the native platform. |
|
1705 * |
|
1706 * @implNote |
|
1707 * This implementation throws {@code UnsupportedOperationException} for |
|
1708 * non-direct buffers when the given unit size is greater then {@code 8}. |
|
1709 * |
|
1710 * @param unitSize |
|
1711 * The unit size in bytes, must be a power of {@code 2} |
|
1712 * |
|
1713 * @return The new byte buffer |
|
1714 * |
|
1715 * @throws IllegalArgumentException |
|
1716 * If the unit size not a power of {@code 2} |
|
1717 * |
|
1718 * @throws UnsupportedOperationException |
|
1719 * If the native platform does not guarantee stable aligned slices |
|
1720 * for the given unit size when managing the memory regions |
|
1721 * of buffers of the same kind as this buffer (direct or |
|
1722 * non-direct). For example, if garbage collection would result |
|
1723 * in the moving of a memory region covered by a non-direct buffer |
|
1724 * from one location to another and both locations have different |
|
1725 * alignment characteristics. |
|
1726 * |
|
1727 * @see #alignmentOffset(int, int) |
|
1728 * @see #slice() |
|
1729 * @since 9 |
|
1730 */ |
|
1731 public final ByteBuffer alignedSlice(int unitSize) { |
|
1732 int pos = position(); |
|
1733 int lim = limit(); |
|
1734 |
|
1735 int pos_mod = alignmentOffset(pos, unitSize); |
|
1736 int lim_mod = alignmentOffset(lim, unitSize); |
|
1737 |
|
1738 // Round up the position to align with unit size |
|
1739 int aligned_pos = (pos_mod > 0) |
|
1740 ? pos + (unitSize - pos_mod) |
|
1741 : pos; |
|
1742 |
|
1743 // Round down the limit to align with unit size |
|
1744 int aligned_lim = lim - lim_mod; |
|
1745 |
|
1746 if (aligned_pos > lim || aligned_lim < pos) { |
|
1747 aligned_pos = aligned_lim = pos; |
|
1748 } |
|
1749 |
|
1750 return slice(aligned_pos, aligned_lim); |
|
1751 } |
|
1752 |
|
1753 abstract ByteBuffer slice(int pos, int lim); |
|
1754 |
1614 // Unchecked accessors, for use by ByteBufferAs-X-Buffer classes |
1755 // Unchecked accessors, for use by ByteBufferAs-X-Buffer classes |
1615 // |
1756 // |
1616 abstract byte _get(int i); // package-private |
1757 abstract byte _get(int i); // package-private |
1617 abstract void _put(int i, byte b); // package-private |
1758 abstract void _put(int i, byte b); // package-private |
1618 |
1759 |