001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package java.nio;
019:
020: import org.apache.harmony.luni.platform.PlatformAddress;
021: import org.apache.harmony.luni.platform.PlatformAddressFactory;
022: import org.apache.harmony.nio.internal.DirectBuffer;
023: import org.apache.harmony.nio.internal.nls.Messages;
024:
025: /**
026: * DirectByteBuffer, ReadWriteDirectByteBuffer and ReadOnlyDirectByteBuffer
027: * compose the implementation of platform memory based byte buffers.
028: * <p>
029: * DirectByteBuffer implements all the shared readonly methods and is extended
030: * by the other two classes.
031: * </p>
032: * <p>
033: * All methods are marked final for runtime performance.
034: * </p>
035: *
036: */
037: abstract class DirectByteBuffer extends BaseByteBuffer implements
038: DirectBuffer {
039:
040: // This class will help us track whether the address is valid or not.
041: static final class SafeAddress {
042: protected volatile boolean isValid = true;
043:
044: protected final PlatformAddress address;
045:
046: protected SafeAddress(PlatformAddress address) {
047: super ();
048: this .address = address;
049: }
050: }
051:
052: // This is a wrapped reference to the base address of the buffer memory.
053: protected final SafeAddress safeAddress;
054:
055: // This is the offset from the base address at which this buffer logically
056: // starts.
057: protected final int offset;
058:
059: /*
060: * Constructs a new direct byte buffer of the given capacity on newly
061: * allocated OS memory. The memory will have been zeroed. When the instance
062: * is discarded the OS memory will be freed if it has not already been done
063: * so by an explicit call to #free(). Callers are encouraged to explicitly
064: * free the memory where possible.
065: */
066: DirectByteBuffer(int capacity) {
067: this (new SafeAddress(PlatformAddressFactory.alloc(capacity,
068: (byte) 0)), capacity, 0);
069: safeAddress.address.autoFree();
070: }
071:
072: DirectByteBuffer(SafeAddress address, int capacity, int offset) {
073: super (capacity);
074: this .safeAddress = address;
075: this .offset = offset;
076: }
077:
078: /*
079: * Override ByteBuffer.get(byte[], int, int) to improve performance.
080: *
081: * (non-Javadoc)
082: *
083: * @see java.nio.ByteBuffer#get(byte[], int, int)
084: */
085: @Override
086: public final ByteBuffer get(byte[] dest, int off, int len) {
087: int length = dest.length;
088: if ((off < 0) || (len < 0) || (long) off + (long) len > length) {
089: throw new IndexOutOfBoundsException();
090: }
091: if (len > remaining()) {
092: throw new BufferUnderflowException();
093: }
094: getBaseAddress()
095: .getByteArray(offset + position, dest, off, len);
096: position += len;
097: return this ;
098: }
099:
100: @Override
101: public final byte get() {
102: if (position == limit) {
103: throw new BufferUnderflowException();
104: }
105: return getBaseAddress().getByte(offset + position++);
106: }
107:
108: @Override
109: public final byte get(int index) {
110: if (index < 0 || index >= limit) {
111: throw new IndexOutOfBoundsException();
112: }
113: return getBaseAddress().getByte(offset + index);
114: }
115:
116: @Override
117: public final double getDouble() {
118: int newPosition = position + 8;
119: if (newPosition > limit) {
120: throw new BufferUnderflowException();
121: }
122: double result = getBaseAddress().getDouble(offset + position,
123: order);
124: position = newPosition;
125: return result;
126: }
127:
128: @Override
129: public final double getDouble(int index) {
130: if (index < 0 || (long) index + 8 > limit) {
131: throw new IndexOutOfBoundsException();
132: }
133: return getBaseAddress().getDouble(offset + index, order);
134: }
135:
136: @Override
137: public final float getFloat() {
138: int newPosition = position + 4;
139: if (newPosition > limit) {
140: throw new BufferUnderflowException();
141: }
142: float result = getBaseAddress().getFloat(offset + position,
143: order);
144: position = newPosition;
145: return result;
146: }
147:
148: @Override
149: public final float getFloat(int index) {
150: if (index < 0 || (long) index + 4 > limit) {
151: throw new IndexOutOfBoundsException();
152: }
153: return getBaseAddress().getFloat(offset + index, order);
154: }
155:
156: @Override
157: public final int getInt() {
158: int newPosition = position + 4;
159: if (newPosition > limit) {
160: throw new BufferUnderflowException();
161: }
162: int result = getBaseAddress().getInt(offset + position, order);
163: position = newPosition;
164: return result;
165: }
166:
167: @Override
168: public final int getInt(int index) {
169: if (index < 0 || (long) index + 4 > limit) {
170: throw new IndexOutOfBoundsException();
171: }
172: return getBaseAddress().getInt(offset + index, order);
173: }
174:
175: @Override
176: public final long getLong() {
177: int newPosition = position + 8;
178: if (newPosition > limit) {
179: throw new BufferUnderflowException();
180: }
181: long result = getBaseAddress()
182: .getLong(offset + position, order);
183: position = newPosition;
184: return result;
185: }
186:
187: @Override
188: public final long getLong(int index) {
189: if (index < 0 || (long) index + 8 > limit) {
190: throw new IndexOutOfBoundsException();
191: }
192: return getBaseAddress().getLong(offset + index, order);
193: }
194:
195: @Override
196: public final short getShort() {
197: int newPosition = position + 2;
198: if (newPosition > limit) {
199: throw new BufferUnderflowException();
200: }
201: short result = getBaseAddress().getShort(offset + position,
202: order);
203: position = newPosition;
204: return result;
205: }
206:
207: @Override
208: public final short getShort(int index) {
209: if (index < 0 || (long) index + 2 > limit) {
210: throw new IndexOutOfBoundsException();
211: }
212: return getBaseAddress().getShort(offset + index, order);
213: }
214:
215: @Override
216: public final boolean isDirect() {
217: return true;
218: }
219:
220: public final boolean isAddressValid() {
221: return safeAddress.isValid;
222: }
223:
224: public final void addressValidityCheck() {
225: if (!isAddressValid()) {
226: // nio.08=Cannot use the direct byte buffer after it has been
227: // explicitly freed.
228: throw new IllegalStateException(Messages
229: .getString("nio.08")); //$NON-NLS-1$
230: }
231: }
232:
233: private void markAddressInvalid() {
234: safeAddress.isValid = false;
235: }
236:
237: /*
238: * Answers the base address of the buffer (i.e. before offset).
239: */
240: public final PlatformAddress getBaseAddress() {
241: addressValidityCheck();
242: return safeAddress.address;
243: }
244:
245: /**
246: * Answers the platform address of the start of this buffer instance.
247: * <em>You must not attempt to free the returned address!!</em> It may not
248: * be an address that was explicitly malloc'ed (i.e. if this buffer is the
249: * result of a split); and it may be memory shared by multiple buffers.
250: * <p>
251: * If you can guarantee that you want to free the underlying memory call the
252: * #free() method on this instance -- generally applications will rely on
253: * the garbage collector to autofree this memory.
254: * </p>
255: *
256: * @return the effective address of the start of the buffer.
257: * @throws IllegalStateException
258: * if this buffer address is known to have been freed
259: * previously.
260: */
261: public final PlatformAddress getEffectiveAddress() {
262: return getBaseAddress().offsetBytes(offset);
263: }
264:
265: /**
266: * Explicitly free the memory used by this direct byte buffer. If the memory
267: * has already been freed then this is a no-op. Once the memory has been
268: * freed then operations requiring access to the memory will throw an
269: * <code>IllegalStateException</code>.
270: * <p>
271: * Note this is is possible that the memory is freed by code that reaches
272: * into the address and explicitly frees it 'beneith' us -- this is bad
273: * form.
274: * </p>
275: */
276: public final void free() {
277: if (isAddressValid()) {
278: markAddressInvalid();
279: safeAddress.address.free();
280: }
281: }
282:
283: @Override
284: final protected byte[] protectedArray() {
285: throw new UnsupportedOperationException();
286: }
287:
288: @Override
289: final protected int protectedArrayOffset() {
290: throw new UnsupportedOperationException();
291: }
292:
293: @Override
294: final protected boolean protectedHasArray() {
295: return false;
296: }
297:
298: public final int getByteCapacity() {
299: return capacity;
300: }
301: }
|