1/* 2 * Copyright (c) 2000, 2021, 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 java.lang.ref.Reference; 32import java.util.Objects; 33import jdk.internal.access.foreign.MemorySegmentProxy; 34import jdk.internal.misc.ScopedMemoryAccess.Scope; 35import jdk.internal.misc.VM; 36import jdk.internal.ref.Cleaner; 37import sun.nio.ch.DirectBuffer; 38 39 40class Direct$Type$Buffer$RW$$BO$ 41#if[rw] 42 extends {#if[byte]?Mapped$Type$Buffer:$Type$Buffer} 43#else[rw] 44 extends Direct$Type$Buffer$BO$ 45#end[rw] 46 implements DirectBuffer 47{ 48 49#if[rw] 50 51 // Cached array base offset 52 private static final long ARRAY_BASE_OFFSET = 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 long address; 77 private long size; 78 private int capacity; 79 80 private Deallocator(long address, long size, int capacity) { 81 assert (address != 0); 82 this.address = address; 83 this.size = size; 84 this.capacity = capacity; 85 } 86 87 public void run() { 88 if (address == 0) { 89 // Paranoia 90 return; 91 } 92 UNSAFE.freeMemory(address); 93 address = 0; 94 Bits.unreserveMemory(size, capacity); 95 } 96 97 } 98 99 private final Cleaner cleaner; 100 101 public Cleaner cleaner() { return cleaner; } 102 103#else[byte] 104 105 public Cleaner cleaner() { return null; } 106 107#end[byte] 108 109#end[rw] 110 111#if[byte] 112 113 // Primary constructor 114 // 115 Direct$Type$Buffer$RW$(int cap) { // package-private 116#if[rw] 117 super(-1, 0, cap, cap, null); 118 boolean pa = VM.isDirectMemoryPageAligned(); 119 int ps = Bits.pageSize(); 120 long size = Math.max(1L, (long)cap + (pa ? ps : 0)); 121 Bits.reserveMemory(size, cap); 122 123 long base = 0; 124 try { 125 base = UNSAFE.allocateMemory(size); 126 } catch (OutOfMemoryError x) { 127 Bits.unreserveMemory(size, cap); 128 throw x; 129 } 130 UNSAFE.setMemory(base, size, (byte) 0); 131 if (pa && (base % ps != 0)) { 132 // Round up to page boundary 133 address = base + ps - (base & (ps - 1)); 134 } else { 135 address = base; 136 } 137 cleaner = Cleaner.create(this, new Deallocator(base, size, cap)); 138 att = null; 139#else[rw] 140 super(cap); 141 this.isReadOnly = true; 142#end[rw] 143 } 144 145#if[rw] 146 147 // Invoked to construct a direct ByteBuffer referring to the block of 148 // memory. A given arbitrary object may also be attached to the buffer. 149 // 150 Direct$Type$Buffer(long addr, int cap, Object ob, MemorySegmentProxy segment) { 151 super(-1, 0, cap, cap, segment); 152 address = addr; 153 cleaner = null; 154 att = ob; 155 } 156 157 // Invoked to construct a direct ByteBuffer referring to the block of 158 // memory. A given arbitrary object may also be attached to the buffer. 159 // 160 Direct$Type$Buffer(long addr, int cap, Object ob, FileDescriptor fd, boolean isSync, MemorySegmentProxy segment) { 161 super(-1, 0, cap, cap, fd, isSync, segment); 162 address = addr; 163 cleaner = null; 164 att = ob; 165 } 166 167 // Invoked only by JNI: NewDirectByteBuffer(void*, long) 168 // 169 private Direct$Type$Buffer(long addr, int cap) { 170 super(-1, 0, cap, cap, null); 171 address = addr; 172 cleaner = null; 173 att = null; 174 } 175 176#end[rw] 177 178 // For memory-mapped buffers -- invoked by FileChannelImpl via reflection 179 // 180 protected Direct$Type$Buffer$RW$(int cap, long addr, 181 FileDescriptor fd, 182 Runnable unmapper, 183 boolean isSync, MemorySegmentProxy segment) 184 { 185#if[rw] 186 super(-1, 0, cap, cap, fd, isSync, segment); 187 address = addr; 188 cleaner = Cleaner.create(this, unmapper); 189 att = null; 190#else[rw] 191 super(cap, addr, fd, unmapper, isSync, segment); 192 this.isReadOnly = true; 193#end[rw] 194 } 195 196#end[byte] 197 198 // For duplicates and slices 199 // 200 Direct$Type$Buffer$RW$$BO$(DirectBuffer db, // package-private 201 int mark, int pos, int lim, int cap, int off, 202#if[byte] 203 FileDescriptor fd, boolean isSync, 204#end[byte] 205 MemorySegmentProxy segment) 206 { 207#if[rw] 208 super(mark, pos, lim, cap, 209#if[byte] 210 fd, isSync, 211#end[byte] 212 segment); 213 address = ((Buffer)db).address + off; 214#if[byte] 215 cleaner = null; 216#end[byte] 217 Object attachment = db.attachment(); 218 att = (attachment == null ? db : attachment); 219#else[rw] 220 super(db, mark, pos, lim, cap, off, 221#if[byte] 222 fd, isSync, 223#end[byte] 224 segment); 225 this.isReadOnly = true; 226#end[rw] 227 } 228 229 @Override 230 Object base() { 231 return null; 232 } 233 234 public {#if[byte]?Mapped$Type$Buffer:$Type$Buffer} slice() { 235 int pos = this.position(); 236 int lim = this.limit(); 237 int rem = (pos <= lim ? lim - pos : 0); 238 int off = (pos << $LG_BYTES_PER_VALUE$); 239 assert (off >= 0); 240 return new Direct$Type$Buffer$RW$$BO$(this, 241 -1, 242 0, 243 rem, 244 rem, 245 off, 246#if[byte] 247 fileDescriptor(), 248 isSync(), 249#end[byte] 250 segment); 251 } 252 253 @Override 254 public {#if[byte]?Mapped$Type$Buffer:$Type$Buffer} slice(int index, int length) { 255 Objects.checkFromIndexSize(index, length, limit()); 256 return new Direct$Type$Buffer$RW$$BO$(this, 257 -1, 258 0, 259 length, 260 length, 261 index << $LG_BYTES_PER_VALUE$, 262#if[byte] 263 fileDescriptor(), 264 isSync(), 265#end[byte] 266 segment); 267 } 268 269 public {#if[byte]?Mapped$Type$Buffer:$Type$Buffer} duplicate() { 270 return new Direct$Type$Buffer$RW$$BO$(this, 271 this.markValue(), 272 this.position(), 273 this.limit(), 274 this.capacity(), 275 0, 276#if[byte] 277 fileDescriptor(), 278 isSync(), 279#end[byte] 280 segment); 281 } 282 283 public $Type$Buffer asReadOnlyBuffer() { 284#if[rw] 285 return new Direct$Type$BufferR$BO$(this, 286 this.markValue(), 287 this.position(), 288 this.limit(), 289 this.capacity(), 290 0, 291#if[byte] 292 fileDescriptor(), 293 isSync(), 294#end[byte] 295 segment); 296#else[rw] 297 return duplicate(); 298#end[rw] 299 } 300 301#if[rw] 302 303 public long address() { 304 Scope scope = scope(); 305 if (scope != null) { 306 if (scope.ownerThread() == null) { 307 throw new UnsupportedOperationException("ByteBuffer derived from shared segments not supported"); 308 } 309 try { 310 scope.checkValidState(); 311 } catch (Scope.ScopedAccessError e) { 312 throw new IllegalStateException("This segment is already closed"); 313 } 314 } 315 return address; 316 } 317 318 private long ix(int i) { 319 return address + ((long)i << $LG_BYTES_PER_VALUE$); 320 } 321 322 public $type$ get() { 323 try { 324 return $fromBits$($swap$(SCOPED_MEMORY_ACCESS.get$Swaptype$(scope(), null, ix(nextGetIndex())))); 325 } finally { 326 Reference.reachabilityFence(this); 327 } 328 } 329 330 public $type$ get(int i) { 331 try { 332 return $fromBits$($swap$(SCOPED_MEMORY_ACCESS.get$Swaptype$(scope(), null, ix(checkIndex(i))))); 333 } finally { 334 Reference.reachabilityFence(this); 335 } 336 } 337 338#if[streamableType] 339 $type$ getUnchecked(int i) { 340 try { 341 return $fromBits$($swap$(SCOPED_MEMORY_ACCESS.get$Swaptype$(null, null, ix(i)))); 342 } finally { 343 Reference.reachabilityFence(this); 344 } 345 } 346#end[streamableType] 347#end[rw] 348 349 public $Type$Buffer put($type$ x) { 350#if[rw] 351 try { 352 SCOPED_MEMORY_ACCESS.put$Swaptype$(scope(), null, ix(nextPutIndex()), $swap$($toBits$(x))); 353 } finally { 354 Reference.reachabilityFence(this); 355 } 356 return this; 357#else[rw] 358 throw new ReadOnlyBufferException(); 359#end[rw] 360 } 361 362 public $Type$Buffer put(int i, $type$ x) { 363#if[rw] 364 try { 365 SCOPED_MEMORY_ACCESS.put$Swaptype$(scope(), null, ix(checkIndex(i)), $swap$($toBits$(x))); 366 } finally { 367 Reference.reachabilityFence(this); 368 } 369 return this; 370#else[rw] 371 throw new ReadOnlyBufferException(); 372#end[rw] 373 } 374 375 public {#if[byte]?Mapped$Type$Buffer:$Type$Buffer} compact() { 376#if[rw] 377 int pos = position(); 378 int lim = limit(); 379 assert (pos <= lim); 380 int rem = (pos <= lim ? lim - pos : 0); 381 try { 382 // null is passed as destination Scope to avoid checking scope() twice 383 SCOPED_MEMORY_ACCESS.copyMemory(scope(), null, null, 384 ix(pos), null, ix(0), (long)rem << $LG_BYTES_PER_VALUE$); 385 } finally { 386 Reference.reachabilityFence(this); 387 } 388 position(rem); 389 limit(capacity()); 390 discardMark(); 391 return this; 392#else[rw] 393 throw new ReadOnlyBufferException(); 394#end[rw] 395 } 396 397 public boolean isDirect() { 398 return true; 399 } 400 401 public boolean isReadOnly() { 402 return {#if[rw]?false:true}; 403 } 404 405 406#if[char] 407 408 public String toString(int start, int end) { 409 Objects.checkFromToIndex(start, end, limit()); 410 try { 411 int len = end - start; 412 char[] ca = new char[len]; 413 CharBuffer cb = CharBuffer.wrap(ca); 414 CharBuffer db = this.duplicate(); 415 db.position(start); 416 db.limit(end); 417 cb.put(db); 418 return new String(ca); 419 } catch (StringIndexOutOfBoundsException x) { 420 throw new IndexOutOfBoundsException(); 421 } 422 } 423 424 425 // --- Methods to support CharSequence --- 426 427 public CharBuffer subSequence(int start, int end) { 428 int pos = position(); 429 int lim = limit(); 430 assert (pos <= lim); 431 pos = (pos <= lim ? pos : lim); 432 int len = lim - pos; 433 434 Objects.checkFromToIndex(start, end, len); 435 return new DirectCharBuffer$RW$$BO$(this, 436 -1, 437 pos + start, 438 pos + end, 439 capacity(), 440 offset, segment); 441 } 442 443#end[char] 444 445 446 447#if[!byte] 448 449 public ByteOrder order() { 450#if[boS] 451 return ((ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) 452 ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN); 453#end[boS] 454#if[boU] 455 return ((ByteOrder.nativeOrder() != ByteOrder.BIG_ENDIAN) 456 ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN); 457#end[boU] 458 } 459 460#end[!byte] 461 462#if[char] 463 ByteOrder charRegionOrder() { 464 return order(); 465 } 466#end[char] 467 468 469#if[byte] 470 // #BIN 471 // 472 // Binary-data access methods for short, char, int, long, float, 473 // and double will be inserted here 474 475#end[byte] 476 477} 478