jdk/src/share/classes/java/nio/Direct-X-Buffer.java
changeset 4135 08d5964ec7d4
parent 4134 430015834eb3
parent 4129 658d1b92c389
child 4140 9c3e48ab69a6
equal deleted inserted replaced
4134:430015834eb3 4135:08d5964ec7d4
     1 /*
       
     2  * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 #warn This file is preprocessed before being compiled
       
    27 
       
    28 package java.nio;
       
    29 
       
    30 import sun.misc.Cleaner;
       
    31 import sun.misc.Unsafe;
       
    32 import sun.nio.ch.DirectBuffer;
       
    33 
       
    34 
       
    35 class Direct$Type$Buffer$RW$$BO$
       
    36 #if[rw]
       
    37     extends {#if[byte]?Mapped$Type$Buffer:$Type$Buffer}
       
    38 #else[rw]
       
    39     extends Direct$Type$Buffer$BO$
       
    40 #end[rw]
       
    41     implements DirectBuffer
       
    42 {
       
    43 
       
    44 #if[rw]
       
    45 
       
    46     // Cached unsafe-access object
       
    47     protected static final Unsafe unsafe = Bits.unsafe();
       
    48 
       
    49     // Cached array base offset
       
    50     private static final long arrayBaseOffset = (long)unsafe.arrayBaseOffset($type$[].class);
       
    51 
       
    52     // Cached unaligned-access capability
       
    53     protected static final boolean unaligned = Bits.unaligned();
       
    54 
       
    55     // Base address, used in all indexing calculations
       
    56     // NOTE: moved up to Buffer.java for speed in JNI GetDirectBufferAddress
       
    57     //    protected long address;
       
    58 
       
    59     // If this buffer is a view of another buffer then we keep a reference to
       
    60     // that buffer so that its memory isn't freed before we're done with it
       
    61     protected Object viewedBuffer = null;
       
    62 
       
    63     public Object viewedBuffer() {
       
    64         return viewedBuffer;
       
    65     }
       
    66 
       
    67 #if[byte]
       
    68 
       
    69     private static class Deallocator
       
    70         implements Runnable
       
    71     {
       
    72 
       
    73         private static Unsafe unsafe = Unsafe.getUnsafe();
       
    74 
       
    75         private long address;
       
    76         private long size;
       
    77         private int capacity;
       
    78 
       
    79         private Deallocator(long address, long size, int capacity) {
       
    80             assert (address != 0);
       
    81             this.address = address;
       
    82             this.size = size;
       
    83             this.capacity = capacity;
       
    84         }
       
    85 
       
    86         public void run() {
       
    87             if (address == 0) {
       
    88                 // Paranoia
       
    89                 return;
       
    90             }
       
    91             unsafe.freeMemory(address);
       
    92             address = 0;
       
    93             Bits.unreserveMemory(size, capacity);
       
    94         }
       
    95 
       
    96     }
       
    97 
       
    98     private final Cleaner cleaner;
       
    99 
       
   100     public Cleaner cleaner() { return cleaner; }
       
   101 
       
   102 #else[byte]
       
   103 
       
   104     public Cleaner cleaner() { return null; }
       
   105 
       
   106 #end[byte]
       
   107 
       
   108 #end[rw]
       
   109 
       
   110 #if[byte]
       
   111 
       
   112     // Primary constructor
       
   113     //
       
   114     Direct$Type$Buffer$RW$(int cap) {                   // package-private
       
   115 #if[rw]
       
   116         super(-1, 0, cap, cap, false);
       
   117         int ps = Bits.pageSize();
       
   118         int size = cap + ps;
       
   119         Bits.reserveMemory(size, cap);
       
   120 
       
   121         long base = 0;
       
   122         try {
       
   123             base = unsafe.allocateMemory(size);
       
   124         } catch (OutOfMemoryError x) {
       
   125             Bits.unreserveMemory(size, cap);
       
   126             throw x;
       
   127         }
       
   128         unsafe.setMemory(base, size, (byte) 0);
       
   129         if (base % ps != 0) {
       
   130             // Round up to page boundary
       
   131             address = base + ps - (base & (ps - 1));
       
   132         } else {
       
   133             address = base;
       
   134         }
       
   135         cleaner = Cleaner.create(this, new Deallocator(base, size, cap));
       
   136 #else[rw]
       
   137         super(cap);
       
   138 #end[rw]
       
   139     }
       
   140 
       
   141 #if[rw]
       
   142 
       
   143     // Invoked only by JNI: NewDirectByteBuffer(void*, long)
       
   144     //
       
   145     private Direct$Type$Buffer(long addr, int cap) {
       
   146         super(-1, 0, cap, cap, false);
       
   147         address = addr;
       
   148         cleaner = null;
       
   149     }
       
   150 
       
   151 #end[rw]
       
   152 
       
   153     // For memory-mapped buffers -- invoked by FileChannelImpl via reflection
       
   154     //
       
   155     protected Direct$Type$Buffer$RW$(int cap, long addr, Runnable unmapper) {
       
   156 #if[rw]
       
   157         super(-1, 0, cap, cap, true);
       
   158         address = addr;
       
   159         viewedBuffer = null;
       
   160         cleaner = Cleaner.create(this, unmapper);
       
   161 #else[rw]
       
   162         super(cap, addr, unmapper);
       
   163 #end[rw]
       
   164     }
       
   165 
       
   166 #end[byte]
       
   167 
       
   168     // For duplicates and slices
       
   169     //
       
   170     Direct$Type$Buffer$RW$$BO$(DirectBuffer db,         // package-private
       
   171                                int mark, int pos, int lim, int cap,
       
   172                                int off)
       
   173     {
       
   174 #if[rw]
       
   175         super(mark, pos, lim, cap);
       
   176         address = db.address() + off;
       
   177         viewedBuffer = db;
       
   178 #if[byte]
       
   179         cleaner = null;
       
   180 #end[byte]
       
   181 #else[rw]
       
   182         super(db, mark, pos, lim, cap, off);
       
   183 #end[rw]
       
   184     }
       
   185 
       
   186     public $Type$Buffer slice() {
       
   187         int pos = this.position();
       
   188         int lim = this.limit();
       
   189         assert (pos <= lim);
       
   190         int rem = (pos <= lim ? lim - pos : 0);
       
   191         int off = (pos << $LG_BYTES_PER_VALUE$);
       
   192         assert (off >= 0);
       
   193         return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, off);
       
   194     }
       
   195 
       
   196     public $Type$Buffer duplicate() {
       
   197         return new Direct$Type$Buffer$RW$$BO$(this,
       
   198                                               this.markValue(),
       
   199                                               this.position(),
       
   200                                               this.limit(),
       
   201                                               this.capacity(),
       
   202                                               0);
       
   203     }
       
   204 
       
   205     public $Type$Buffer asReadOnlyBuffer() {
       
   206 #if[rw]
       
   207         return new Direct$Type$BufferR$BO$(this,
       
   208                                            this.markValue(),
       
   209                                            this.position(),
       
   210                                            this.limit(),
       
   211                                            this.capacity(),
       
   212                                            0);
       
   213 #else[rw]
       
   214         return duplicate();
       
   215 #end[rw]
       
   216     }
       
   217 
       
   218 #if[rw]
       
   219 
       
   220     public long address() {
       
   221         return address;
       
   222     }
       
   223 
       
   224     private long ix(int i) {
       
   225         return address + (i << $LG_BYTES_PER_VALUE$);
       
   226     }
       
   227 
       
   228     public $type$ get() {
       
   229         return $fromBits$($swap$(unsafe.get$Swaptype$(ix(nextGetIndex()))));
       
   230     }
       
   231 
       
   232     public $type$ get(int i) {
       
   233         return $fromBits$($swap$(unsafe.get$Swaptype$(ix(checkIndex(i)))));
       
   234     }
       
   235 
       
   236     public $Type$Buffer get($type$[] dst, int offset, int length) {
       
   237 #if[rw]
       
   238         if ((length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_TO_ARRAY_THRESHOLD) {
       
   239             checkBounds(offset, length, dst.length);
       
   240             int pos = position();
       
   241             int lim = limit();
       
   242             assert (pos <= lim);
       
   243             int rem = (pos <= lim ? lim - pos : 0);
       
   244             if (length > rem)
       
   245                 throw new BufferUnderflowException();
       
   246 
       
   247 #if[!byte]
       
   248             if (order() != ByteOrder.nativeOrder())
       
   249                 Bits.copyTo$Memtype$Array(ix(pos), dst,
       
   250                                           offset << $LG_BYTES_PER_VALUE$,
       
   251                                           length << $LG_BYTES_PER_VALUE$);
       
   252             else
       
   253 #end[!byte]
       
   254                 Bits.copyToArray(ix(pos), dst, arrayBaseOffset,
       
   255                                  offset << $LG_BYTES_PER_VALUE$,
       
   256                                  length << $LG_BYTES_PER_VALUE$);
       
   257             position(pos + length);
       
   258         } else {
       
   259             super.get(dst, offset, length);
       
   260         }
       
   261         return this;
       
   262 #else[rw]
       
   263         throw new ReadOnlyBufferException();
       
   264 #end[rw]
       
   265     }
       
   266 
       
   267 #end[rw]
       
   268 
       
   269     public $Type$Buffer put($type$ x) {
       
   270 #if[rw]
       
   271         unsafe.put$Swaptype$(ix(nextPutIndex()), $swap$($toBits$(x)));
       
   272         return this;
       
   273 #else[rw]
       
   274         throw new ReadOnlyBufferException();
       
   275 #end[rw]
       
   276     }
       
   277 
       
   278     public $Type$Buffer put(int i, $type$ x) {
       
   279 #if[rw]
       
   280         unsafe.put$Swaptype$(ix(checkIndex(i)), $swap$($toBits$(x)));
       
   281         return this;
       
   282 #else[rw]
       
   283         throw new ReadOnlyBufferException();
       
   284 #end[rw]
       
   285     }
       
   286 
       
   287     public $Type$Buffer put($Type$Buffer src) {
       
   288 #if[rw]
       
   289         if (src instanceof Direct$Type$Buffer$BO$) {
       
   290             if (src == this)
       
   291                 throw new IllegalArgumentException();
       
   292             Direct$Type$Buffer$RW$$BO$ sb = (Direct$Type$Buffer$RW$$BO$)src;
       
   293 
       
   294             int spos = sb.position();
       
   295             int slim = sb.limit();
       
   296             assert (spos <= slim);
       
   297             int srem = (spos <= slim ? slim - spos : 0);
       
   298 
       
   299             int pos = position();
       
   300             int lim = limit();
       
   301             assert (pos <= lim);
       
   302             int rem = (pos <= lim ? lim - pos : 0);
       
   303 
       
   304             if (srem > rem)
       
   305                 throw new BufferOverflowException();
       
   306             unsafe.copyMemory(sb.ix(spos), ix(pos), srem << $LG_BYTES_PER_VALUE$);
       
   307             sb.position(spos + srem);
       
   308             position(pos + srem);
       
   309         } else if (src.hb != null) {
       
   310 
       
   311             int spos = src.position();
       
   312             int slim = src.limit();
       
   313             assert (spos <= slim);
       
   314             int srem = (spos <= slim ? slim - spos : 0);
       
   315 
       
   316             put(src.hb, src.offset + spos, srem);
       
   317             src.position(spos + srem);
       
   318 
       
   319         } else {
       
   320             super.put(src);
       
   321         }
       
   322         return this;
       
   323 #else[rw]
       
   324         throw new ReadOnlyBufferException();
       
   325 #end[rw]
       
   326     }
       
   327 
       
   328     public $Type$Buffer put($type$[] src, int offset, int length) {
       
   329 #if[rw]
       
   330         if ((length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_FROM_ARRAY_THRESHOLD) {
       
   331             checkBounds(offset, length, src.length);
       
   332             int pos = position();
       
   333             int lim = limit();
       
   334             assert (pos <= lim);
       
   335             int rem = (pos <= lim ? lim - pos : 0);
       
   336             if (length > rem)
       
   337                 throw new BufferOverflowException();
       
   338 
       
   339 #if[!byte]
       
   340             if (order() != ByteOrder.nativeOrder())
       
   341                 Bits.copyFrom$Memtype$Array(src, offset << $LG_BYTES_PER_VALUE$,
       
   342                                             ix(pos), length << $LG_BYTES_PER_VALUE$);
       
   343             else
       
   344 #end[!byte]
       
   345                 Bits.copyFromArray(src, arrayBaseOffset, offset << $LG_BYTES_PER_VALUE$,
       
   346                                    ix(pos), length << $LG_BYTES_PER_VALUE$);
       
   347             position(pos + length);
       
   348         } else {
       
   349             super.put(src, offset, length);
       
   350         }
       
   351         return this;
       
   352 #else[rw]
       
   353         throw new ReadOnlyBufferException();
       
   354 #end[rw]
       
   355     }
       
   356 
       
   357     public $Type$Buffer compact() {
       
   358 #if[rw]
       
   359         int pos = position();
       
   360         int lim = limit();
       
   361         assert (pos <= lim);
       
   362         int rem = (pos <= lim ? lim - pos : 0);
       
   363 
       
   364         unsafe.copyMemory(ix(pos), ix(0), rem << $LG_BYTES_PER_VALUE$);
       
   365         position(rem);
       
   366         limit(capacity());
       
   367         discardMark();
       
   368         return this;
       
   369 #else[rw]
       
   370         throw new ReadOnlyBufferException();
       
   371 #end[rw]
       
   372     }
       
   373 
       
   374     public boolean isDirect() {
       
   375         return true;
       
   376     }
       
   377 
       
   378     public boolean isReadOnly() {
       
   379         return {#if[rw]?false:true};
       
   380     }
       
   381 
       
   382 
       
   383 #if[char]
       
   384 
       
   385     public String toString(int start, int end) {
       
   386         if ((end > limit()) || (start > end))
       
   387             throw new IndexOutOfBoundsException();
       
   388         try {
       
   389             int len = end - start;
       
   390             char[] ca = new char[len];
       
   391             CharBuffer cb = CharBuffer.wrap(ca);
       
   392             CharBuffer db = this.duplicate();
       
   393             db.position(start);
       
   394             db.limit(end);
       
   395             cb.put(db);
       
   396             return new String(ca);
       
   397         } catch (StringIndexOutOfBoundsException x) {
       
   398             throw new IndexOutOfBoundsException();
       
   399         }
       
   400     }
       
   401 
       
   402 
       
   403     // --- Methods to support CharSequence ---
       
   404 
       
   405     public CharBuffer subSequence(int start, int end) {
       
   406         int pos = position();
       
   407         int lim = limit();
       
   408         assert (pos <= lim);
       
   409         pos = (pos <= lim ? pos : lim);
       
   410         int len = lim - pos;
       
   411 
       
   412         if ((start < 0) || (end > len) || (start > end))
       
   413             throw new IndexOutOfBoundsException();
       
   414         return new DirectCharBuffer$RW$$BO$(this,
       
   415                                             -1,
       
   416                                             pos + start,
       
   417                                             pos + end,
       
   418                                             capacity(),
       
   419                                             offset);
       
   420     }
       
   421 
       
   422 #end[char]
       
   423 
       
   424 
       
   425 
       
   426 #if[!byte]
       
   427 
       
   428     public ByteOrder order() {
       
   429 #if[boS]
       
   430         return ((ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN)
       
   431                 ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
       
   432 #end[boS]
       
   433 #if[boU]
       
   434         return ((ByteOrder.nativeOrder() != ByteOrder.BIG_ENDIAN)
       
   435                 ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
       
   436 #end[boU]
       
   437     }
       
   438 
       
   439 #end[!byte]
       
   440 
       
   441 
       
   442 
       
   443 #if[byte]
       
   444 
       
   445     byte _get(int i) {                          // package-private
       
   446         return unsafe.getByte(address + i);
       
   447     }
       
   448 
       
   449     void _put(int i, byte b) {                  // package-private
       
   450 #if[rw]
       
   451         unsafe.putByte(address + i, b);
       
   452 #else[rw]
       
   453         throw new ReadOnlyBufferException();
       
   454 #end[rw]
       
   455     }
       
   456 
       
   457     // #BIN
       
   458     //
       
   459     // Binary-data access methods  for short, char, int, long, float,
       
   460     // and double will be inserted here
       
   461 
       
   462 #end[byte]
       
   463 
       
   464 }