40 |
|
|
41 |
import gnu.classpath.RawData; |
import gnu.classpath.RawData; |
42 |
|
|
43 |
final class DirectByteBufferImpl extends ByteBuffer |
abstract class DirectByteBufferImpl extends ByteBuffer |
44 |
{ |
{ |
45 |
/** Used by MappedByteBufferImpl and when slicing to prevent premature GC. */ |
/** The owner is used to keep alive the object that actually owns the |
46 |
protected Object owner; |
* memory. There are three possibilities: |
47 |
|
* 1) owner == this: We allocated the memory and we should free it, |
48 |
RawData address; |
* but *only* in finalize (if we've been sliced |
49 |
private boolean readOnly; |
* other objects will also have access to the |
50 |
|
* memory). |
51 |
public DirectByteBufferImpl(RawData address, long len) |
* 2) owner == null: The byte buffer was created thru |
52 |
{ |
* JNI.NewDirectByteBuffer. The JNI code is |
53 |
this(null, address, (int) len, (int) len, 0, false); |
* responsible for freeing the memory. |
54 |
} |
* 3) owner == some other object: The other object allocated the |
55 |
|
* memory and should free it. |
56 |
public DirectByteBufferImpl(Object owner, RawData address, |
*/ |
57 |
int capacity, int limit, |
private final Object owner; |
58 |
int position, boolean readOnly) |
final RawData address; |
59 |
|
|
60 |
|
final static class ReadOnly extends DirectByteBufferImpl |
61 |
|
{ |
62 |
|
ReadOnly(Object owner, RawData address, |
63 |
|
int capacity, int limit, |
64 |
|
int position) |
65 |
|
{ |
66 |
|
super(owner, address, capacity, limit, position); |
67 |
|
} |
68 |
|
|
69 |
|
public ByteBuffer put(byte value) |
70 |
|
{ |
71 |
|
throw new ReadOnlyBufferException (); |
72 |
|
} |
73 |
|
|
74 |
|
public ByteBuffer put(int index, byte value) |
75 |
|
{ |
76 |
|
throw new ReadOnlyBufferException (); |
77 |
|
} |
78 |
|
|
79 |
|
public boolean isReadOnly() |
80 |
|
{ |
81 |
|
return true; |
82 |
|
} |
83 |
|
} |
84 |
|
|
85 |
|
final static class ReadWrite extends DirectByteBufferImpl |
86 |
|
{ |
87 |
|
ReadWrite(int capacity) |
88 |
|
{ |
89 |
|
super(capacity); |
90 |
|
} |
91 |
|
|
92 |
|
ReadWrite(Object owner, RawData address, |
93 |
|
int capacity, int limit, |
94 |
|
int position) |
95 |
|
{ |
96 |
|
super(owner, address, capacity, limit, position); |
97 |
|
} |
98 |
|
|
99 |
|
public boolean isReadOnly() |
100 |
|
{ |
101 |
|
return false; |
102 |
|
} |
103 |
|
} |
104 |
|
|
105 |
|
DirectByteBufferImpl(int capacity) |
106 |
|
{ |
107 |
|
super(capacity, capacity, 0, -1); |
108 |
|
this.owner = this; |
109 |
|
this.address = VMDirectByteBuffer.allocate(capacity); |
110 |
|
} |
111 |
|
|
112 |
|
DirectByteBufferImpl(Object owner, RawData address, |
113 |
|
int capacity, int limit, |
114 |
|
int position) |
115 |
{ |
{ |
116 |
super(capacity, limit, position, -1); |
super(capacity, limit, position, -1); |
|
this.address = address; |
|
|
this.readOnly = readOnly; |
|
117 |
this.owner = owner; |
this.owner = owner; |
118 |
|
this.address = address; |
119 |
} |
} |
120 |
|
|
121 |
/** |
/** |
123 |
*/ |
*/ |
124 |
public static ByteBuffer allocate(int capacity) |
public static ByteBuffer allocate(int capacity) |
125 |
{ |
{ |
126 |
return new DirectByteBufferImpl(VMDirectByteBuffer.allocate(capacity), |
return new DirectByteBufferImpl.ReadWrite(capacity); |
|
capacity); |
|
127 |
} |
} |
128 |
|
|
129 |
protected void finalize() throws Throwable |
protected void finalize() throws Throwable |
130 |
{ |
{ |
131 |
VMDirectByteBuffer.free(address); |
if (owner == this) |
132 |
|
VMDirectByteBuffer.free(address); |
133 |
} |
} |
134 |
|
|
135 |
public byte get() |
public byte get() |
163 |
|
|
164 |
public ByteBuffer put(byte value) |
public ByteBuffer put(byte value) |
165 |
{ |
{ |
|
checkIfReadOnly(); |
|
166 |
checkForOverflow(); |
checkForOverflow(); |
167 |
|
|
168 |
int pos = position(); |
int pos = position(); |
173 |
|
|
174 |
public ByteBuffer put(int index, byte value) |
public ByteBuffer put(int index, byte value) |
175 |
{ |
{ |
|
checkIfReadOnly(); |
|
176 |
checkIndex(index); |
checkIndex(index); |
177 |
|
|
178 |
VMDirectByteBuffer.put(address, index, value); |
VMDirectByteBuffer.put(address, index, value); |
200 |
public ByteBuffer slice() |
public ByteBuffer slice() |
201 |
{ |
{ |
202 |
int rem = remaining(); |
int rem = remaining(); |
203 |
return new DirectByteBufferImpl |
if (isReadOnly()) |
204 |
|
return new DirectByteBufferImpl.ReadOnly |
205 |
|
(owner, VMDirectByteBuffer.adjustAddress(address, position()), |
206 |
|
rem, rem, 0); |
207 |
|
else |
208 |
|
return new DirectByteBufferImpl.ReadWrite |
209 |
(owner, VMDirectByteBuffer.adjustAddress(address, position()), |
(owner, VMDirectByteBuffer.adjustAddress(address, position()), |
210 |
rem, rem, 0, isReadOnly()); |
rem, rem, 0); |
211 |
} |
} |
212 |
|
|
213 |
private ByteBuffer duplicate(boolean readOnly) |
private ByteBuffer duplicate(boolean readOnly) |
216 |
reset(); |
reset(); |
217 |
int mark = position(); |
int mark = position(); |
218 |
position(pos); |
position(pos); |
219 |
DirectByteBufferImpl result |
DirectByteBufferImpl result; |
220 |
= new DirectByteBufferImpl(owner, address, capacity(), limit(), |
if (readOnly) |
221 |
pos, readOnly); |
result = new DirectByteBufferImpl.ReadOnly(owner, address, capacity(), |
222 |
|
limit(), pos); |
223 |
|
else |
224 |
|
result = new DirectByteBufferImpl.ReadWrite(owner, address, capacity(), |
225 |
|
limit(), pos); |
226 |
|
|
227 |
if (mark != pos) |
if (mark != pos) |
228 |
{ |
{ |
229 |
result.position(mark); |
result.position(mark); |
243 |
return duplicate(true); |
return duplicate(true); |
244 |
} |
} |
245 |
|
|
|
public boolean isReadOnly() |
|
|
{ |
|
|
return readOnly; |
|
|
} |
|
|
|
|
246 |
public boolean isDirect() |
public boolean isDirect() |
247 |
{ |
{ |
248 |
return true; |
return true; |