src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template
changeset 47216 71c04702a3d5
parent 36933 3e6453e2d833
child 48356 29e165bdf669
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template	Tue Sep 12 19:03:39 2017 +0200
@@ -0,0 +1,516 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#warn This file is preprocessed before being compiled
+
+package java.nio;
+
+import java.io.FileDescriptor;
+import jdk.internal.misc.Unsafe;
+import jdk.internal.misc.VM;
+import jdk.internal.ref.Cleaner;
+import sun.nio.ch.DirectBuffer;
+
+
+class Direct$Type$Buffer$RW$$BO$
+#if[rw]
+    extends {#if[byte]?Mapped$Type$Buffer:$Type$Buffer}
+#else[rw]
+    extends Direct$Type$Buffer$BO$
+#end[rw]
+    implements DirectBuffer
+{
+
+#if[rw]
+
+    // Cached unsafe-access object
+    protected static final Unsafe unsafe = Bits.unsafe();
+
+    // Cached array base offset
+    private static final long arrayBaseOffset = (long)unsafe.arrayBaseOffset($type$[].class);
+
+    // Cached unaligned-access capability
+    protected static final boolean unaligned = Bits.unaligned();
+
+    // Base address, used in all indexing calculations
+    // NOTE: moved up to Buffer.java for speed in JNI GetDirectBufferAddress
+    //    protected long address;
+
+    // An object attached to this buffer. If this buffer is a view of another
+    // buffer then we use this field to keep a reference to that buffer to
+    // ensure that its memory isn't freed before we are done with it.
+    private final Object att;
+
+    public Object attachment() {
+        return att;
+    }
+
+#if[byte]
+
+    private static class Deallocator
+        implements Runnable
+    {
+
+        private static Unsafe unsafe = Unsafe.getUnsafe();
+
+        private long address;
+        private long size;
+        private int capacity;
+
+        private Deallocator(long address, long size, int capacity) {
+            assert (address != 0);
+            this.address = address;
+            this.size = size;
+            this.capacity = capacity;
+        }
+
+        public void run() {
+            if (address == 0) {
+                // Paranoia
+                return;
+            }
+            unsafe.freeMemory(address);
+            address = 0;
+            Bits.unreserveMemory(size, capacity);
+        }
+
+    }
+
+    private final Cleaner cleaner;
+
+    public Cleaner cleaner() { return cleaner; }
+
+#else[byte]
+
+    public Cleaner cleaner() { return null; }
+
+#end[byte]
+
+#end[rw]
+
+#if[byte]
+
+    // Primary constructor
+    //
+    Direct$Type$Buffer$RW$(int cap) {                   // package-private
+#if[rw]
+        super(-1, 0, cap, cap);
+        boolean pa = VM.isDirectMemoryPageAligned();
+        int ps = Bits.pageSize();
+        long size = Math.max(1L, (long)cap + (pa ? ps : 0));
+        Bits.reserveMemory(size, cap);
+
+        long base = 0;
+        try {
+            base = unsafe.allocateMemory(size);
+        } catch (OutOfMemoryError x) {
+            Bits.unreserveMemory(size, cap);
+            throw x;
+        }
+        unsafe.setMemory(base, size, (byte) 0);
+        if (pa && (base % ps != 0)) {
+            // Round up to page boundary
+            address = base + ps - (base & (ps - 1));
+        } else {
+            address = base;
+        }
+        cleaner = Cleaner.create(this, new Deallocator(base, size, cap));
+        att = null;
+#else[rw]
+        super(cap);
+        this.isReadOnly = true;
+#end[rw]
+    }
+
+#if[rw]
+
+    // Invoked to construct a direct ByteBuffer referring to the block of
+    // memory. A given arbitrary object may also be attached to the buffer.
+    //
+    Direct$Type$Buffer(long addr, int cap, Object ob) {
+        super(-1, 0, cap, cap);
+        address = addr;
+        cleaner = null;
+        att = ob;
+    }
+
+
+    // Invoked only by JNI: NewDirectByteBuffer(void*, long)
+    //
+    private Direct$Type$Buffer(long addr, int cap) {
+        super(-1, 0, cap, cap);
+        address = addr;
+        cleaner = null;
+        att = null;
+    }
+
+#end[rw]
+
+    // For memory-mapped buffers -- invoked by FileChannelImpl via reflection
+    //
+    protected Direct$Type$Buffer$RW$(int cap, long addr,
+                                     FileDescriptor fd,
+                                     Runnable unmapper)
+    {
+#if[rw]
+        super(-1, 0, cap, cap, fd);
+        address = addr;
+        cleaner = Cleaner.create(this, unmapper);
+        att = null;
+#else[rw]
+        super(cap, addr, fd, unmapper);
+        this.isReadOnly = true;
+#end[rw]
+    }
+
+#end[byte]
+
+    // For duplicates and slices
+    //
+    Direct$Type$Buffer$RW$$BO$(DirectBuffer db,         // package-private
+                               int mark, int pos, int lim, int cap,
+                               int off)
+    {
+#if[rw]
+        super(mark, pos, lim, cap);
+        address = db.address() + off;
+#if[byte]
+        cleaner = null;
+#end[byte]
+        att = db;
+#else[rw]
+        super(db, mark, pos, lim, cap, off);
+        this.isReadOnly = true;
+#end[rw]
+    }
+
+    public $Type$Buffer slice() {
+        int pos = this.position();
+        int lim = this.limit();
+        assert (pos <= lim);
+        int rem = (pos <= lim ? lim - pos : 0);
+        int off = (pos << $LG_BYTES_PER_VALUE$);
+        assert (off >= 0);
+        return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, off);
+    }
+
+#if[byte]
+    public $Type$Buffer slice(int pos, int lim) {
+        assert (pos >= 0);
+        assert (pos <= lim);
+        int rem = lim - pos;
+        return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, pos);
+    }
+#end[byte]
+
+    public $Type$Buffer duplicate() {
+        return new Direct$Type$Buffer$RW$$BO$(this,
+                                              this.markValue(),
+                                              this.position(),
+                                              this.limit(),
+                                              this.capacity(),
+                                              0);
+    }
+
+    public $Type$Buffer asReadOnlyBuffer() {
+#if[rw]
+        return new Direct$Type$BufferR$BO$(this,
+                                           this.markValue(),
+                                           this.position(),
+                                           this.limit(),
+                                           this.capacity(),
+                                           0);
+#else[rw]
+        return duplicate();
+#end[rw]
+    }
+
+#if[rw]
+
+    public long address() {
+        return address;
+    }
+
+    private long ix(int i) {
+        return address + ((long)i << $LG_BYTES_PER_VALUE$);
+    }
+
+    public $type$ get() {
+        return $fromBits$($swap$(unsafe.get$Swaptype$(ix(nextGetIndex()))));
+    }
+
+    public $type$ get(int i) {
+        return $fromBits$($swap$(unsafe.get$Swaptype$(ix(checkIndex(i)))));
+    }
+
+#if[streamableType]
+    $type$ getUnchecked(int i) {
+        return $fromBits$($swap$(unsafe.get$Swaptype$(ix(i))));
+    }
+#end[streamableType]
+
+    public $Type$Buffer get($type$[] dst, int offset, int length) {
+#if[rw]
+        if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_TO_ARRAY_THRESHOLD) {
+            checkBounds(offset, length, dst.length);
+            int pos = position();
+            int lim = limit();
+            assert (pos <= lim);
+            int rem = (pos <= lim ? lim - pos : 0);
+            if (length > rem)
+                throw new BufferUnderflowException();
+
+            long dstOffset = arrayBaseOffset + ((long)offset << $LG_BYTES_PER_VALUE$);
+#if[!byte]
+            if (order() != ByteOrder.nativeOrder())
+                unsafe.copySwapMemory(null,
+                                      ix(pos),
+                                      dst,
+                                      dstOffset,
+                                      (long)length << $LG_BYTES_PER_VALUE$,
+                                      (long)1 << $LG_BYTES_PER_VALUE$);
+            else
+#end[!byte]
+                unsafe.copyMemory(null,
+                                  ix(pos),
+                                  dst,
+                                  dstOffset,
+                                  (long)length << $LG_BYTES_PER_VALUE$);
+            position(pos + length);
+        } else {
+            super.get(dst, offset, length);
+        }
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+#end[rw]
+
+    public $Type$Buffer put($type$ x) {
+#if[rw]
+        unsafe.put$Swaptype$(ix(nextPutIndex()), $swap$($toBits$(x)));
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer put(int i, $type$ x) {
+#if[rw]
+        unsafe.put$Swaptype$(ix(checkIndex(i)), $swap$($toBits$(x)));
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer put($Type$Buffer src) {
+#if[rw]
+        if (src instanceof Direct$Type$Buffer$BO$) {
+            if (src == this)
+                throw createSameBufferException();
+            Direct$Type$Buffer$RW$$BO$ sb = (Direct$Type$Buffer$RW$$BO$)src;
+
+            int spos = sb.position();
+            int slim = sb.limit();
+            assert (spos <= slim);
+            int srem = (spos <= slim ? slim - spos : 0);
+
+            int pos = position();
+            int lim = limit();
+            assert (pos <= lim);
+            int rem = (pos <= lim ? lim - pos : 0);
+
+            if (srem > rem)
+                throw new BufferOverflowException();
+            unsafe.copyMemory(sb.ix(spos), ix(pos), (long)srem << $LG_BYTES_PER_VALUE$);
+            sb.position(spos + srem);
+            position(pos + srem);
+        } else if (src.hb != null) {
+
+            int spos = src.position();
+            int slim = src.limit();
+            assert (spos <= slim);
+            int srem = (spos <= slim ? slim - spos : 0);
+
+            put(src.hb, src.offset + spos, srem);
+            src.position(spos + srem);
+
+        } else {
+            super.put(src);
+        }
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer put($type$[] src, int offset, int length) {
+#if[rw]
+        if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_FROM_ARRAY_THRESHOLD) {
+            checkBounds(offset, length, src.length);
+            int pos = position();
+            int lim = limit();
+            assert (pos <= lim);
+            int rem = (pos <= lim ? lim - pos : 0);
+            if (length > rem)
+                throw new BufferOverflowException();
+
+            long srcOffset = arrayBaseOffset + ((long)offset << $LG_BYTES_PER_VALUE$);
+#if[!byte]
+            if (order() != ByteOrder.nativeOrder())
+                unsafe.copySwapMemory(src,
+                                      srcOffset,
+                                      null,
+                                      ix(pos),
+                                      (long)length << $LG_BYTES_PER_VALUE$,
+                                      (long)1 << $LG_BYTES_PER_VALUE$);
+            else
+#end[!byte]
+                unsafe.copyMemory(src,
+                                  srcOffset,
+                                  null,
+                                  ix(pos),
+                                  (long)length << $LG_BYTES_PER_VALUE$);
+            position(pos + length);
+        } else {
+            super.put(src, offset, length);
+        }
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer compact() {
+#if[rw]
+        int pos = position();
+        int lim = limit();
+        assert (pos <= lim);
+        int rem = (pos <= lim ? lim - pos : 0);
+
+        unsafe.copyMemory(ix(pos), ix(0), (long)rem << $LG_BYTES_PER_VALUE$);
+        position(rem);
+        limit(capacity());
+        discardMark();
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public boolean isDirect() {
+        return true;
+    }
+
+    public boolean isReadOnly() {
+        return {#if[rw]?false:true};
+    }
+
+
+#if[char]
+
+    public String toString(int start, int end) {
+        if ((end > limit()) || (start > end))
+            throw new IndexOutOfBoundsException();
+        try {
+            int len = end - start;
+            char[] ca = new char[len];
+            CharBuffer cb = CharBuffer.wrap(ca);
+            CharBuffer db = this.duplicate();
+            db.position(start);
+            db.limit(end);
+            cb.put(db);
+            return new String(ca);
+        } catch (StringIndexOutOfBoundsException x) {
+            throw new IndexOutOfBoundsException();
+        }
+    }
+
+
+    // --- Methods to support CharSequence ---
+
+    public CharBuffer subSequence(int start, int end) {
+        int pos = position();
+        int lim = limit();
+        assert (pos <= lim);
+        pos = (pos <= lim ? pos : lim);
+        int len = lim - pos;
+
+        if ((start < 0) || (end > len) || (start > end))
+            throw new IndexOutOfBoundsException();
+        return new DirectCharBuffer$RW$$BO$(this,
+                                            -1,
+                                            pos + start,
+                                            pos + end,
+                                            capacity(),
+                                            offset);
+    }
+
+#end[char]
+
+
+
+#if[!byte]
+
+    public ByteOrder order() {
+#if[boS]
+        return ((ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN)
+                ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
+#end[boS]
+#if[boU]
+        return ((ByteOrder.nativeOrder() != ByteOrder.BIG_ENDIAN)
+                ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
+#end[boU]
+    }
+
+#end[!byte]
+
+
+
+#if[byte]
+
+    byte _get(int i) {                          // package-private
+        return unsafe.getByte(address + i);
+    }
+
+    void _put(int i, byte b) {                  // package-private
+#if[rw]
+        unsafe.putByte(address + i, b);
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    // #BIN
+    //
+    // Binary-data access methods  for short, char, int, long, float,
+    // and double will be inserted here
+
+#end[byte]
+
+}