1/* 2 * Copyright (c) 2000, 2016, 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 28package java.nio; 29 30import java.io.FileDescriptor; 31import jdk.internal.misc.Unsafe; 32import jdk.internal.misc.VM; 33import jdk.internal.ref.Cleaner; 34import sun.nio.ch.DirectBuffer; 35 36 37class 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 // An object attached to this buffer. If this buffer is a view of another 62 // buffer then we use this field to keep a reference to that buffer to 63 // ensure that its memory isn't freed before we are done with it. 64 private final Object att; 65 66 public Object attachment() { 67 return att; 68 } 69 70#if[byte] 71 72 private static class Deallocator 73 implements Runnable 74 { 75 76 private static Unsafe unsafe = Unsafe.getUnsafe(); 77 78 private long address; 79 private long size; 80 private int capacity; 81 82 private Deallocator(long address, long size, int capacity) { 83 assert (address != 0); 84 this.address = address; 85 this.size = size; 86 this.capacity = capacity; 87 } 88 89 public void run() { 90 if (address == 0) { 91 // Paranoia 92 return; 93 } 94 unsafe.freeMemory(address); 95 address = 0; 96 Bits.unreserveMemory(size, capacity); 97 } 98 99 } 100 101 private final Cleaner cleaner; 102 103 public Cleaner cleaner() { return cleaner; } 104 105#else[byte] 106 107 public Cleaner cleaner() { return null; } 108 109#end[byte] 110 111#end[rw] 112 113#if[byte] 114 115 // Primary constructor 116 // 117 Direct$Type$Buffer$RW$(int cap) { // package-private 118#if[rw] 119 super(-1, 0, cap, cap); 120 boolean pa = VM.isDirectMemoryPageAligned(); 121 int ps = Bits.pageSize(); 122 long size = Math.max(1L, (long)cap + (pa ? ps : 0)); 123 Bits.reserveMemory(size, cap); 124 125 long base = 0; 126 try { 127 base = unsafe.allocateMemory(size); 128 } catch (OutOfMemoryError x) { 129 Bits.unreserveMemory(size, cap); 130 throw x; 131 } 132 unsafe.setMemory(base, size, (byte) 0); 133 if (pa && (base % ps != 0)) { 134 // Round up to page boundary 135 address = base + ps - (base & (ps - 1)); 136 } else { 137 address = base; 138 } 139 cleaner = Cleaner.create(this, new Deallocator(base, size, cap)); 140 att = null; 141#else[rw] 142 super(cap); 143 this.isReadOnly = true; 144#end[rw] 145 } 146 147#if[rw] 148 149 // Invoked to construct a direct ByteBuffer referring to the block of 150 // memory. A given arbitrary object may also be attached to the buffer. 151 // 152 Direct$Type$Buffer(long addr, int cap, Object ob) { 153 super(-1, 0, cap, cap); 154 address = addr; 155 cleaner = null; 156 att = ob; 157 } 158 159 160 // Invoked only by JNI: NewDirectByteBuffer(void*, long) 161 // 162 private Direct$Type$Buffer(long addr, int cap) { 163 super(-1, 0, cap, cap); 164 address = addr; 165 cleaner = null; 166 att = null; 167 } 168 169#end[rw] 170 171 // For memory-mapped buffers -- invoked by FileChannelImpl via reflection 172 // 173 protected Direct$Type$Buffer$RW$(int cap, long addr, 174 FileDescriptor fd, 175 Runnable unmapper) 176 { 177#if[rw] 178 super(-1, 0, cap, cap, fd); 179 address = addr; 180 cleaner = Cleaner.create(this, unmapper); 181 att = null; 182#else[rw] 183 super(cap, addr, fd, unmapper); 184 this.isReadOnly = true; 185#end[rw] 186 } 187 188#end[byte] 189 190 // For duplicates and slices 191 // 192 Direct$Type$Buffer$RW$$BO$(DirectBuffer db, // package-private 193 int mark, int pos, int lim, int cap, 194 int off) 195 { 196#if[rw] 197 super(mark, pos, lim, cap); 198 address = db.address() + off; 199#if[byte] 200 cleaner = null; 201#end[byte] 202 att = db; 203#else[rw] 204 super(db, mark, pos, lim, cap, off); 205 this.isReadOnly = true; 206#end[rw] 207 } 208 209 public $Type$Buffer slice() { 210 int pos = this.position(); 211 int lim = this.limit(); 212 assert (pos <= lim); 213 int rem = (pos <= lim ? lim - pos : 0); 214 int off = (pos << $LG_BYTES_PER_VALUE$); 215 assert (off >= 0); 216 return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, off); 217 } 218 219#if[byte] 220 public $Type$Buffer slice(int pos, int lim) { 221 assert (pos >= 0); 222 assert (pos <= lim); 223 int rem = lim - pos; 224 return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, pos); 225 } 226#end[byte] 227 228 public $Type$Buffer duplicate() { 229 return new Direct$Type$Buffer$RW$$BO$(this, 230 this.markValue(), 231 this.position(), 232 this.limit(), 233 this.capacity(), 234 0); 235 } 236 237 public $Type$Buffer asReadOnlyBuffer() { 238#if[rw] 239 return new Direct$Type$BufferR$BO$(this, 240 this.markValue(), 241 this.position(), 242 this.limit(), 243 this.capacity(), 244 0); 245#else[rw] 246 return duplicate(); 247#end[rw] 248 } 249 250#if[rw] 251 252 public long address() { 253 return address; 254 } 255 256 private long ix(int i) { 257 return address + ((long)i << $LG_BYTES_PER_VALUE$); 258 } 259 260 public $type$ get() { 261 return $fromBits$($swap$(unsafe.get$Swaptype$(ix(nextGetIndex())))); 262 } 263 264 public $type$ get(int i) { 265 return $fromBits$($swap$(unsafe.get$Swaptype$(ix(checkIndex(i))))); 266 } 267 268#if[streamableType] 269 $type$ getUnchecked(int i) { 270 return $fromBits$($swap$(unsafe.get$Swaptype$(ix(i)))); 271 } 272#end[streamableType] 273 274 public $Type$Buffer get($type$[] dst, int offset, int length) { 275#if[rw] 276 if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_TO_ARRAY_THRESHOLD) { 277 checkBounds(offset, length, dst.length); 278 int pos = position(); 279 int lim = limit(); 280 assert (pos <= lim); 281 int rem = (pos <= lim ? lim - pos : 0); 282 if (length > rem) 283 throw new BufferUnderflowException(); 284 285 long dstOffset = arrayBaseOffset + ((long)offset << $LG_BYTES_PER_VALUE$); 286#if[!byte] 287 if (order() != ByteOrder.nativeOrder()) 288 unsafe.copySwapMemory(null, 289 ix(pos), 290 dst, 291 dstOffset, 292 (long)length << $LG_BYTES_PER_VALUE$, 293 (long)1 << $LG_BYTES_PER_VALUE$); 294 else 295#end[!byte] 296 unsafe.copyMemory(null, 297 ix(pos), 298 dst, 299 dstOffset, 300 (long)length << $LG_BYTES_PER_VALUE$); 301 position(pos + length); 302 } else { 303 super.get(dst, offset, length); 304 } 305 return this; 306#else[rw] 307 throw new ReadOnlyBufferException(); 308#end[rw] 309 } 310 311#end[rw] 312 313 public $Type$Buffer put($type$ x) { 314#if[rw] 315 unsafe.put$Swaptype$(ix(nextPutIndex()), $swap$($toBits$(x))); 316 return this; 317#else[rw] 318 throw new ReadOnlyBufferException(); 319#end[rw] 320 } 321 322 public $Type$Buffer put(int i, $type$ x) { 323#if[rw] 324 unsafe.put$Swaptype$(ix(checkIndex(i)), $swap$($toBits$(x))); 325 return this; 326#else[rw] 327 throw new ReadOnlyBufferException(); 328#end[rw] 329 } 330 331 public $Type$Buffer put($Type$Buffer src) { 332#if[rw] 333 if (src instanceof Direct$Type$Buffer$BO$) { 334 if (src == this) 335 throw createSameBufferException(); 336 Direct$Type$Buffer$RW$$BO$ sb = (Direct$Type$Buffer$RW$$BO$)src; 337 338 int spos = sb.position(); 339 int slim = sb.limit(); 340 assert (spos <= slim); 341 int srem = (spos <= slim ? slim - spos : 0); 342 343 int pos = position(); 344 int lim = limit(); 345 assert (pos <= lim); 346 int rem = (pos <= lim ? lim - pos : 0); 347 348 if (srem > rem) 349 throw new BufferOverflowException(); 350 unsafe.copyMemory(sb.ix(spos), ix(pos), (long)srem << $LG_BYTES_PER_VALUE$); 351 sb.position(spos + srem); 352 position(pos + srem); 353 } else if (src.hb != null) { 354 355 int spos = src.position(); 356 int slim = src.limit(); 357 assert (spos <= slim); 358 int srem = (spos <= slim ? slim - spos : 0); 359 360 put(src.hb, src.offset + spos, srem); 361 src.position(spos + srem); 362 363 } else { 364 super.put(src); 365 } 366 return this; 367#else[rw] 368 throw new ReadOnlyBufferException(); 369#end[rw] 370 } 371 372 public $Type$Buffer put($type$[] src, int offset, int length) { 373#if[rw] 374 if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_FROM_ARRAY_THRESHOLD) { 375 checkBounds(offset, length, src.length); 376 int pos = position(); 377 int lim = limit(); 378 assert (pos <= lim); 379 int rem = (pos <= lim ? lim - pos : 0); 380 if (length > rem) 381 throw new BufferOverflowException(); 382 383 long srcOffset = arrayBaseOffset + ((long)offset << $LG_BYTES_PER_VALUE$); 384#if[!byte] 385 if (order() != ByteOrder.nativeOrder()) 386 unsafe.copySwapMemory(src, 387 srcOffset, 388 null, 389 ix(pos), 390 (long)length << $LG_BYTES_PER_VALUE$, 391 (long)1 << $LG_BYTES_PER_VALUE$); 392 else 393#end[!byte] 394 unsafe.copyMemory(src, 395 srcOffset, 396 null, 397 ix(pos), 398 (long)length << $LG_BYTES_PER_VALUE$); 399 position(pos + length); 400 } else { 401 super.put(src, offset, length); 402 } 403 return this; 404#else[rw] 405 throw new ReadOnlyBufferException(); 406#end[rw] 407 } 408 409 public $Type$Buffer compact() { 410#if[rw] 411 int pos = position(); 412 int lim = limit(); 413 assert (pos <= lim); 414 int rem = (pos <= lim ? lim - pos : 0); 415 416 unsafe.copyMemory(ix(pos), ix(0), (long)rem << $LG_BYTES_PER_VALUE$); 417 position(rem); 418 limit(capacity()); 419 discardMark(); 420 return this; 421#else[rw] 422 throw new ReadOnlyBufferException(); 423#end[rw] 424 } 425 426 public boolean isDirect() { 427 return true; 428 } 429 430 public boolean isReadOnly() { 431 return {#if[rw]?false:true}; 432 } 433 434 435#if[char] 436 437 public String toString(int start, int end) { 438 if ((end > limit()) || (start > end)) 439 throw new IndexOutOfBoundsException(); 440 try { 441 int len = end - start; 442 char[] ca = new char[len]; 443 CharBuffer cb = CharBuffer.wrap(ca); 444 CharBuffer db = this.duplicate(); 445 db.position(start); 446 db.limit(end); 447 cb.put(db); 448 return new String(ca); 449 } catch (StringIndexOutOfBoundsException x) { 450 throw new IndexOutOfBoundsException(); 451 } 452 } 453 454 455 // --- Methods to support CharSequence --- 456 457 public CharBuffer subSequence(int start, int end) { 458 int pos = position(); 459 int lim = limit(); 460 assert (pos <= lim); 461 pos = (pos <= lim ? pos : lim); 462 int len = lim - pos; 463 464 if ((start < 0) || (end > len) || (start > end)) 465 throw new IndexOutOfBoundsException(); 466 return new DirectCharBuffer$RW$$BO$(this, 467 -1, 468 pos + start, 469 pos + end, 470 capacity(), 471 offset); 472 } 473 474#end[char] 475 476 477 478#if[!byte] 479 480 public ByteOrder order() { 481#if[boS] 482 return ((ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) 483 ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN); 484#end[boS] 485#if[boU] 486 return ((ByteOrder.nativeOrder() != ByteOrder.BIG_ENDIAN) 487 ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN); 488#end[boU] 489 } 490 491#end[!byte] 492 493 494 495#if[byte] 496 497 byte _get(int i) { // package-private 498 return unsafe.getByte(address + i); 499 } 500 501 void _put(int i, byte b) { // package-private 502#if[rw] 503 unsafe.putByte(address + i, b); 504#else[rw] 505 throw new ReadOnlyBufferException(); 506#end[rw] 507 } 508 509 // #BIN 510 // 511 // Binary-data access methods for short, char, int, long, float, 512 // and double will be inserted here 513 514#end[byte] 515 516} 517