001/*
002 * Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026#warn This file is preprocessed before being compiled
027
028package java.nio;
029
030import sun.misc.Cleaner;
031import sun.misc.Unsafe;
032import sun.nio.ch.DirectBuffer;
033import sun.nio.ch.FileChannelImpl;
034
035
036class Direct$Type$Buffer$RW$$BO$
037#if[rw]
038 extends {#if[byte]?Mapped$Type$Buffer:$Type$Buffer}
039#else[rw]
040 extends Direct$Type$Buffer$BO$
041#end[rw]
042 implements DirectBuffer
043{
044
045#if[rw]
046
047 // Cached unsafe-access object
048 protected static final Unsafe unsafe = Bits.unsafe();
049
050 // Cached unaligned-access capability
051 protected static final boolean unaligned = Bits.unaligned();
052
053 // Base address, used in all indexing calculations
054 // NOTE: moved up to Buffer.java for speed in JNI GetDirectBufferAddress
055 // protected long address;
056
057 // If this buffer is a view of another buffer then we keep a reference to
058 // that buffer so that its memory isn't freed before we're done with it
059 protected Object viewedBuffer = null;
060
061 public Object viewedBuffer() {
062 return viewedBuffer;
063 }
064
065#if[byte]
066
067 private static class Deallocator
068 implements Runnable
069 {
070
071 private static Unsafe unsafe = Unsafe.getUnsafe();
072
073 private long address;
074 private int capacity;
075
076 private Deallocator(long address, int capacity) {
077 assert (address != 0);
078 this .address = address;
079 this .capacity = capacity;
080 }
081
082 public void run() {
083 if (address == 0) {
084 // Paranoia
085 return;
086 }
087 unsafe.freeMemory(address);
088 address = 0;
089 Bits.unreserveMemory(capacity);
090 }
091
092 }
093
094 private final Cleaner cleaner;
095
096 public Cleaner cleaner() { return cleaner; }
097
098#else[byte]
099
100 public Cleaner cleaner() { return null; }
101
102#end[byte]
103
104#end[rw]
105
106#if[byte]
107
108 // Primary constructor
109 //
110 Direct$Type$Buffer$RW$(int cap) { // package-private
111#if[rw]
112 super (-1, 0, cap, cap, false);
113 Bits.reserveMemory(cap);
114 int ps = Bits.pageSize();
115 long base = 0;
116 try {
117 base = unsafe.allocateMemory(cap + ps);
118 } catch (OutOfMemoryError x) {
119 Bits.unreserveMemory(cap);
120 throw x;
121 }
122 unsafe.setMemory(base, cap + ps, (byte) 0);
123 if (base % ps != 0) {
124 // Round up to page boundary
125 address = base + ps - (base & (ps - 1));
126 } else {
127 address = base;
128 }
129 cleaner = Cleaner.create(this , new Deallocator(base, cap));
130#else[rw]
131 super (cap);
132#end[rw]
133 }
134
135#if[rw]
136
137 // Invoked only by JNI: NewDirectByteBuffer(void*, long)
138 //
139 private Direct$Type$Buffer(long addr, int cap) {
140 super (-1, 0, cap, cap, false);
141 address = addr;
142 cleaner = null;
143 }
144
145#end[rw]
146
147 // For memory-mapped buffers -- invoked by FileChannelImpl via reflection
148 //
149 protected Direct$Type$Buffer$RW$(int cap, long addr, Runnable unmapper) {
150#if[rw]
151 super (-1, 0, cap, cap, true);
152 address = addr;
153 viewedBuffer = null;
154 cleaner = Cleaner.create(this , unmapper);
155#else[rw]
156 super (cap, addr, unmapper);
157#end[rw]
158 }
159
160#end[byte]
161
162 // For duplicates and slices
163 //
164 Direct$Type$Buffer$RW$$BO$(DirectBuffer db, // package-private
165 int mark, int pos, int lim, int cap,
166 int off)
167 {
168#if[rw]
169 super (mark, pos, lim, cap);
170 address = db.address() + off;
171 viewedBuffer = db;
172#if[byte]
173 cleaner = null;
174#end[byte]
175#else[rw]
176 super (db, mark, pos, lim, cap, off);
177#end[rw]
178 }
179
180 public $Type$Buffer slice() {
181 int pos = this .position();
182 int lim = this .limit();
183 assert (pos <= lim);
184 int rem = (pos <= lim ? lim - pos : 0);
185 int off = (pos << $LG_BYTES_PER_VALUE$);
186 assert (off >= 0);
187 return new Direct$Type$Buffer$RW$$BO$(this , -1, 0, rem, rem, off);
188 }
189
190 public $Type$Buffer duplicate() {
191 return new Direct$Type$Buffer$RW$$BO$(this ,
192 this .markValue(),
193 this .position(),
194 this .limit(),
195 this .capacity(),
196 0);
197 }
198
199 public $Type$Buffer asReadOnlyBuffer() {
200#if[rw]
201 return new Direct$Type$BufferR$BO$(this ,
202 this .markValue(),
203 this .position(),
204 this .limit(),
205 this .capacity(),
206 0);
207#else[rw]
208 return duplicate();
209#end[rw]
210 }
211
212#if[rw]
213
214 public long address() {
215 return address;
216 }
217
218 private long ix(int i) {
219 return address + (i << $LG_BYTES_PER_VALUE$);
220 }
221
222 public $type$ get() {
223 return $fromBits$($swap$(unsafe.get$Swaptype$(ix(nextGetIndex()))));
224 }
225
226 public $type$ get(int i) {
227 return $fromBits$($swap$(unsafe.get$Swaptype$(ix(checkIndex(i)))));
228 }
229
230 public $Type$Buffer get($type$[] dst, int offset, int length) {
231#if[rw]
232 if ((length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_TO_ARRAY_THRESHOLD) {
233 checkBounds(offset, length, dst.length);
234 int pos = position();
235 int lim = limit();
236 assert (pos <= lim);
237 int rem = (pos <= lim ? lim - pos : 0);
238 if (length > rem)
239 throw new BufferUnderflowException();
240
241 if (order() != ByteOrder.nativeOrder())
242 Bits.copyTo$Memtype$Array(ix(pos), dst,
243 offset << $LG_BYTES_PER_VALUE$,
244 length << $LG_BYTES_PER_VALUE$);
245 else
246 Bits.copyToByteArray(ix(pos), dst,
247 offset << $LG_BYTES_PER_VALUE$,
248 length << $LG_BYTES_PER_VALUE$);
249 position(pos + length);
250 } else {
251 super .get(dst, offset, length);
252 }
253 return this ;
254#else[rw]
255 throw new ReadOnlyBufferException();
256#end[rw]
257 }
258
259#end[rw]
260
261 public $Type$Buffer put($type$ x) {
262#if[rw]
263 unsafe.put$Swaptype$(ix(nextPutIndex()), $swap$($toBits$(x)));
264 return this ;
265#else[rw]
266 throw new ReadOnlyBufferException();
267#end[rw]
268 }
269
270 public $Type$Buffer put(int i, $type$ x) {
271#if[rw]
272 unsafe.put$Swaptype$(ix(checkIndex(i)), $swap$($toBits$(x)));
273 return this ;
274#else[rw]
275 throw new ReadOnlyBufferException();
276#end[rw]
277 }
278
279 public $Type$Buffer put($Type$Buffer src) {
280#if[rw]
281 if (src instanceof Direct$Type$Buffer$BO$) {
282 if (src == this )
283 throw new IllegalArgumentException();
284 Direct$Type$Buffer$RW$$BO$ sb = (Direct$Type$Buffer$RW$$BO$)src;
285
286 int spos = sb.position();
287 int slim = sb.limit();
288 assert (spos <= slim);
289 int srem = (spos <= slim ? slim - spos : 0);
290
291 int pos = position();
292 int lim = limit();
293 assert (pos <= lim);
294 int rem = (pos <= lim ? lim - pos : 0);
295
296 if (srem > rem)
297 throw new BufferOverflowException();
298 unsafe.copyMemory(sb.ix(spos), ix(pos), srem << $LG_BYTES_PER_VALUE$);
299 sb.position(spos + srem);
300 position(pos + srem);
301 } else if (src.hb != null) {
302
303 int spos = src.position();
304 int slim = src.limit();
305 assert (spos <= slim);
306 int srem = (spos <= slim ? slim - spos : 0);
307
308 put(src.hb, src.offset + spos, srem);
309 src.position(spos + srem);
310
311 } else {
312 super .put(src);
313 }
314 return this ;
315#else[rw]
316 throw new ReadOnlyBufferException();
317#end[rw]
318 }
319
320 public $Type$Buffer put($type$[] src, int offset, int length) {
321#if[rw]
322 if ((length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_FROM_ARRAY_THRESHOLD) {
323 checkBounds(offset, length, src.length);
324 int pos = position();
325 int lim = limit();
326 assert (pos <= lim);
327 int rem = (pos <= lim ? lim - pos : 0);
328 if (length > rem)
329 throw new BufferOverflowException();
330
331 if (order() != ByteOrder.nativeOrder())
332 Bits.copyFrom$Memtype$Array(src, offset << $LG_BYTES_PER_VALUE$,
333 ix(pos), length << $LG_BYTES_PER_VALUE$);
334 else
335 Bits.copyFromByteArray(src, offset << $LG_BYTES_PER_VALUE$,
336 ix(pos), length << $LG_BYTES_PER_VALUE$);
337 position(pos + length);
338 } else {
339 super .put(src, offset, length);
340 }
341 return this ;
342#else[rw]
343 throw new ReadOnlyBufferException();
344#end[rw]
345 }
346
347 public $Type$Buffer compact() {
348#if[rw]
349 int pos = position();
350 int lim = limit();
351 assert (pos <= lim);
352 int rem = (pos <= lim ? lim - pos : 0);
353
354 unsafe.copyMemory(ix(pos), ix(0), rem << $LG_BYTES_PER_VALUE$);
355 position(rem);
356 limit(capacity());
357 return this ;
358#else[rw]
359 throw new ReadOnlyBufferException();
360#end[rw]
361 }
362
363 public boolean isDirect() {
364 return true;
365 }
366
367 public boolean isReadOnly() {
368 return {#if[rw]?false:true};
369 }
370
371
372#if[char]
373
374 public String toString(int start, int end) {
375 if ((end > limit()) || (start > end))
376 throw new IndexOutOfBoundsException();
377 try {
378 int len = end - start;
379 char[] ca = new char[len];
380 CharBuffer cb = CharBuffer.wrap(ca);
381 CharBuffer db = this .duplicate();
382 db.position(start);
383 db.limit(end);
384 cb.put(db);
385 return new String(ca);
386 } catch (StringIndexOutOfBoundsException x) {
387 throw new IndexOutOfBoundsException();
388 }
389 }
390
391
392 // --- Methods to support CharSequence ---
393
394 public CharSequence subSequence(int start, int end) {
395 int pos = position();
396 int lim = limit();
397 assert (pos <= lim);
398 pos = (pos <= lim ? pos : lim);
399 int len = lim - pos;
400
401 if ((start < 0) || (end > len) || (start > end))
402 throw new IndexOutOfBoundsException();
403 int sublen = end - start;
404 int off = (pos + start) << $LG_BYTES_PER_VALUE$;
405 assert (off >= 0);
406 return new DirectCharBuffer$RW$$BO$(this , -1, 0, sublen, sublen, off);
407 }
408
409#end[char]
410
411
412
413#if[!byte]
414
415 public ByteOrder order() {
416#if[boS]
417 return ((ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN)
418 ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
419#end[boS]
420#if[boU]
421 return ((ByteOrder.nativeOrder() != ByteOrder.BIG_ENDIAN)
422 ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
423#end[boU]
424 }
425
426#end[!byte]
427
428
429
430#if[byte]
431
432 byte _get(int i) { // package-private
433 return unsafe.getByte(address + i);
434 }
435
436 void _put(int i, byte b) { // package-private
437#if[rw]
438 unsafe.putByte(address + i, b);
439#else[rw]
440 throw new ReadOnlyBufferException();
441#end[rw]
442 }
443
444 // #BIN
445 //
446 // Binary-data access methods for short, char, int, long, float,
447 // and double will be inserted here
448
449#end[byte]
450
451}
|