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