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