diff -r 74e9f4b90006 -r 3e6453e2d833 jdk/src/java.base/share/classes/java/nio/X-Buffer.java.template --- a/jdk/src/java.base/share/classes/java/nio/X-Buffer.java.template Mon Mar 21 11:21:08 2016 +0100 +++ b/jdk/src/java.base/share/classes/java/nio/X-Buffer.java.template Thu Mar 24 11:21:18 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -269,7 +269,7 @@ // final $type$[] hb; // Non-null only for heap buffers final int offset; - boolean isReadOnly; // Valid only for heap buffers + boolean isReadOnly; // Creates a new buffer with the given mark, position, limit, capacity, // backing array, and array offset @@ -530,6 +530,10 @@ * it will be read-only if, and only if, this buffer is read-only.

* * @return The new $type$ buffer +#if[byte] + * + * @see #alignedSlice(int) +#end[byte] */ public abstract $Type$Buffer slice(); @@ -1611,6 +1615,143 @@ return this; } + /** + * Returns the memory address, pointing to the byte at the given index, + * modulus the given unit size. + * + *

A return value greater than zero indicates the address of the byte at + * the index is misaligned for the unit size, and the value's quantity + * indicates how much the index should be rounded up or down to locate a + * byte at an aligned address. Otherwise, a value of {@code 0} indicates + * that the address of the byte at the index is aligned for the unit size. + * + * @apiNote + * This method may be utilized to determine if unit size bytes from an + * index can be accessed atomically, if supported by the native platform. + * + * @implNote + * This implementation throws {@code UnsupportedOperationException} for + * non-direct buffers when the given unit size is greater then {@code 8}. + * + * @param index + * The index to query for alignment offset, must be non-negative, no + * upper bounds check is performed + * + * @param unitSize + * The unit size in bytes, must be a power of {@code 2} + * + * @return The indexed byte's memory address modulus the unit size + * + * @throws IllegalArgumentException + * If the index is negative or the unit size is not a power of + * {@code 2} + * + * @throws UnsupportedOperationException + * If the native platform does not guarantee stable alignment offset + * values for the given unit size when managing the memory regions + * of buffers of the same kind as this buffer (direct or + * non-direct). For example, if garbage collection would result + * in the moving of a memory region covered by a non-direct buffer + * from one location to another and both locations have different + * alignment characteristics. + * + * @see #alignedSlice(int) + * @since 9 + */ + public final int alignmentOffset(int index, int unitSize) { + if (index < 0) + throw new IllegalArgumentException("Index less than zero: " + index); + if (unitSize < 1 || (unitSize & (unitSize - 1)) != 0) + throw new IllegalArgumentException("Unit size not a power of two: " + unitSize); + if (unitSize > 8 && !isDirect()) + throw new UnsupportedOperationException("Unit size unsupported for non-direct buffers: " + unitSize); + + return (int) ((address + index) % unitSize); + } + + /** + * Creates a new byte buffer whose content is a shared and aligned + * subsequence of this buffer's content. + * + *

The content of the new buffer will start at this buffer's current + * position rounded up to the index of the nearest aligned byte for the + * given unit size, and end at this buffer's limit rounded down to the index + * of the nearest aligned byte for the given unit size. + * If rounding results in out-of-bound values then the new buffer's capacity + * and limit will be zero. If rounding is within bounds the following + * expressions will be true for a new buffer {@code nb} and unit size + * {@code unitSize}: + *

{@code
+     * nb.alignmentOffset(0, unitSize) == 0
+     * nb.alignmentOffset(nb.limit(), unitSize) == 0
+     * }
+ * + *

Changes to this buffer's content will be visible in the new + * buffer, and vice versa; the two buffers' position, limit, and mark + * values will be independent. + * + *

The new buffer's position will be zero, its capacity and its limit + * will be the number of bytes remaining in this buffer or fewer subject to + * alignment, its mark will be undefined, and its byte order will be + * {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}. + * + * The new buffer will be direct if, and only if, this buffer is direct, and + * it will be read-only if, and only if, this buffer is read-only.

+ * + * @apiNote + * This method may be utilized to create a new buffer where unit size bytes + * from index, that is a multiple of the unit size, may be accessed + * atomically, if supported by the native platform. + * + * @implNote + * This implementation throws {@code UnsupportedOperationException} for + * non-direct buffers when the given unit size is greater then {@code 8}. + * + * @param unitSize + * The unit size in bytes, must be a power of {@code 2} + * + * @return The new byte buffer + * + * @throws IllegalArgumentException + * If the unit size not a power of {@code 2} + * + * @throws UnsupportedOperationException + * If the native platform does not guarantee stable aligned slices + * for the given unit size when managing the memory regions + * of buffers of the same kind as this buffer (direct or + * non-direct). For example, if garbage collection would result + * in the moving of a memory region covered by a non-direct buffer + * from one location to another and both locations have different + * alignment characteristics. + * + * @see #alignmentOffset(int, int) + * @see #slice() + * @since 9 + */ + public final ByteBuffer alignedSlice(int unitSize) { + int pos = position(); + int lim = limit(); + + int pos_mod = alignmentOffset(pos, unitSize); + int lim_mod = alignmentOffset(lim, unitSize); + + // Round up the position to align with unit size + int aligned_pos = (pos_mod > 0) + ? pos + (unitSize - pos_mod) + : pos; + + // Round down the limit to align with unit size + int aligned_lim = lim - lim_mod; + + if (aligned_pos > lim || aligned_lim < pos) { + aligned_pos = aligned_lim = pos; + } + + return slice(aligned_pos, aligned_lim); + } + + abstract ByteBuffer slice(int pos, int lim); + // Unchecked accessors, for use by ByteBufferAs-X-Buffer classes // abstract byte _get(int i); // package-private