+2004-11-24 Jeroen Frijters <address@bogus.example.com>
+
+ * java/nio/DirectByteBufferImpl.java
+ (ReadOnly): New inner subclass.
+ (ReadWrite): New inner subclass.
+ (owner): Made final and private.
+ (address): Made final.
+ (DirectByteBufferImpl(int)): New constructor.
+ (DirectByteBufferImpl(Object,RawData,int,int,int)): New constructor.
+ (DirectByteBufferImpl(Object,RawData,int,int,int,boolean)): Removed.
+ (allocate): Modified to instantiate ReadWrite subclass.
+ (finalize): Fixed to only free the buffer, if we own it.
+ (put): Removed read-only check.
+ (slice, duplicate): Modified to instantiate appropriate subclass.
+ (isReadOnly): Removed.
+ * java/nio/MappedByteBufferImpl.java
+ (slice, duplicate): Modified to instantiate appropriate
+ DirectByteBufferImpl subclass.
+
2004-11-24 Michael Koch <konqueror@gmx.de>
* gnu/java/nio/NIOServerSocket.java: Added email to @author tag.
import gnu.gcj.RawData;
-final class DirectByteBufferImpl extends ByteBuffer
+abstract class DirectByteBufferImpl extends ByteBuffer
{
- /** Used by MappedByteBufferImpl and when slicing to prevent premature GC. */
- protected Object owner;
-
- RawData address;
- private boolean readOnly;
-
- public DirectByteBufferImpl(RawData address, long len)
- {
- this(null, address, (int) len, (int) len, 0, false);
- }
-
- public DirectByteBufferImpl(Object owner, RawData address,
- int capacity, int limit,
- int position, boolean readOnly)
+ /** The owner is used to keep alive the object that actually owns the
+ * memory. There are three possibilities:
+ * 1) owner == this: We allocated the memory and we should free it,
+ * but *only* in finalize (if we've been sliced
+ * other objects will also have access to the
+ * memory).
+ * 2) owner == null: The byte buffer was created thru
+ * JNI.NewDirectByteBuffer. The JNI code is
+ * responsible for freeing the memory.
+ * 3) owner == some other object: The other object allocated the
+ * memory and should free it.
+ */
+ private final Object owner;
+ final RawData address;
+
+ final static class ReadOnly extends DirectByteBufferImpl
+ {
+ ReadOnly(Object owner, RawData address,
+ int capacity, int limit,
+ int position)
+ {
+ super(owner, address, capacity, limit, position);
+ }
+
+ public ByteBuffer put(byte value)
+ {
+ throw new ReadOnlyBufferException ();
+ }
+
+ public ByteBuffer put(int index, byte value)
+ {
+ throw new ReadOnlyBufferException ();
+ }
+
+ public boolean isReadOnly()
+ {
+ return true;
+ }
+ }
+
+ final static class ReadWrite extends DirectByteBufferImpl
+ {
+ ReadWrite(int capacity)
+ {
+ super(capacity);
+ }
+
+ ReadWrite(Object owner, RawData address,
+ int capacity, int limit,
+ int position)
+ {
+ super(owner, address, capacity, limit, position);
+ }
+
+ public boolean isReadOnly()
+ {
+ return false;
+ }
+ }
+
+ DirectByteBufferImpl(int capacity)
+ {
+ super(capacity, capacity, 0, -1);
+ this.owner = this;
+ this.address = VMDirectByteBuffer.allocate(capacity);
+ }
+
+ DirectByteBufferImpl(Object owner, RawData address,
+ int capacity, int limit,
+ int position)
{
super(capacity, limit, position, -1);
- this.address = address;
- this.readOnly = readOnly;
this.owner = owner;
+ this.address = address;
}
/**
*/
public static ByteBuffer allocate(int capacity)
{
- return new DirectByteBufferImpl(VMDirectByteBuffer.allocate(capacity),
- capacity);
+ return new DirectByteBufferImpl.ReadWrite(capacity);
}
protected void finalize() throws Throwable
{
- VMDirectByteBuffer.free(address);
+ if (owner == this)
+ VMDirectByteBuffer.free(address);
}
public byte get()
public ByteBuffer put(byte value)
{
- checkIfReadOnly();
checkForOverflow();
int pos = position();
public ByteBuffer put(int index, byte value)
{
- checkIfReadOnly();
checkIndex(index);
VMDirectByteBuffer.put(address, index, value);
public ByteBuffer slice()
{
int rem = remaining();
- return new DirectByteBufferImpl
+ if (isReadOnly())
+ return new DirectByteBufferImpl.ReadOnly
+ (owner, VMDirectByteBuffer.adjustAddress(address, position()),
+ rem, rem, 0);
+ else
+ return new DirectByteBufferImpl.ReadWrite
(owner, VMDirectByteBuffer.adjustAddress(address, position()),
- rem, rem, 0, isReadOnly());
+ rem, rem, 0);
}
private ByteBuffer duplicate(boolean readOnly)
reset();
int mark = position();
position(pos);
- DirectByteBufferImpl result
- = new DirectByteBufferImpl(owner, address, capacity(), limit(),
- pos, readOnly);
+ DirectByteBufferImpl result;
+ if (readOnly)
+ result = new DirectByteBufferImpl.ReadOnly(owner, address, capacity(),
+ limit(), pos);
+ else
+ result = new DirectByteBufferImpl.ReadWrite(owner, address, capacity(),
+ limit(), pos);
+
if (mark != pos)
{
result.position(mark);
return duplicate(true);
}
- public boolean isReadOnly()
- {
- return readOnly;
- }
-
public boolean isDirect()
{
return true;
public ByteBuffer slice()
{
int rem = remaining();
- return new DirectByteBufferImpl
+ if (isReadOnly())
+ return new DirectByteBufferImpl.ReadOnly
(this, VMDirectByteBuffer.adjustAddress(address, position()),
- rem, rem, 0, isReadOnly());
+ rem, rem, 0);
+ else
+ return new DirectByteBufferImpl.ReadWrite
+ (this, VMDirectByteBuffer.adjustAddress(address, position()),
+ rem, rem, 0);
}
private ByteBuffer duplicate(boolean readOnly)
reset();
int mark = position();
position(pos);
- DirectByteBufferImpl result
- = new DirectByteBufferImpl(this, address, capacity(), limit(),
- pos, readOnly);
+ DirectByteBufferImpl result;
+ if (readOnly)
+ result = new DirectByteBufferImpl.ReadOnly(this, address, capacity(),
+ limit(), pos);
+ else
+ result = new DirectByteBufferImpl.ReadWrite(this, address, capacity(),
+ limit(), pos);
+
if (mark != pos)
{
result.position(mark);