--- a/jdk/src/share/classes/sun/nio/ch/IOVecWrapper.java Tue Aug 10 13:15:40 2010 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/IOVecWrapper.java Thu Aug 12 19:53:25 2010 +0100
@@ -25,6 +25,7 @@
package sun.nio.ch;
+import java.nio.ByteBuffer;
import sun.misc.*;
@@ -43,23 +44,98 @@
class IOVecWrapper {
// Miscellaneous constants
- static int BASE_OFFSET = 0;
- static int LEN_OFFSET;
- static int SIZE_IOVEC;
+ private static final int BASE_OFFSET = 0;
+ private static final int LEN_OFFSET;
+ private static final int SIZE_IOVEC;
// The iovec array
- private AllocatedNativeObject vecArray;
+ private final AllocatedNativeObject vecArray;
+
+ // Number of elements in iovec array
+ private final int size;
+
+ // Buffers and position/remaining corresponding to elements in iovec array
+ private final ByteBuffer[] buf;
+ private final int[] position;
+ private final int[] remaining;
+
+ // Shadow buffers for cases when original buffer is substituted
+ private final ByteBuffer[] shadow;
// Base address of this array
- long address;
+ final long address;
// Address size in bytes
static int addressSize;
- IOVecWrapper(int newSize) {
- newSize = (newSize + 1) * SIZE_IOVEC;
- vecArray = new AllocatedNativeObject(newSize, false);
- address = vecArray.address();
+ private static class Deallocator implements Runnable {
+ private final AllocatedNativeObject obj;
+ Deallocator(AllocatedNativeObject obj) {
+ this.obj = obj;
+ }
+ public void run() {
+ obj.free();
+ }
+ }
+
+ // per thread IOVecWrapper
+ private static final ThreadLocal<IOVecWrapper> cached =
+ new ThreadLocal<IOVecWrapper>();
+
+ private IOVecWrapper(int size) {
+ this.size = size;
+ this.buf = new ByteBuffer[size];
+ this.position = new int[size];
+ this.remaining = new int[size];
+ this.shadow = new ByteBuffer[size];
+ this.vecArray = new AllocatedNativeObject(size * SIZE_IOVEC, false);
+ this.address = vecArray.address();
+ }
+
+ static IOVecWrapper get(int size) {
+ IOVecWrapper wrapper = cached.get();
+ if (wrapper != null && wrapper.size < size) {
+ // not big enough; eagerly release memory
+ wrapper.vecArray.free();
+ wrapper = null;
+ }
+ if (wrapper == null) {
+ wrapper = new IOVecWrapper(size);
+ Cleaner.create(wrapper, new Deallocator(wrapper.vecArray));
+ cached.set(wrapper);
+ }
+ return wrapper;
+ }
+
+ void setBuffer(int i, ByteBuffer buf, int pos, int rem) {
+ this.buf[i] = buf;
+ this.position[i] = pos;
+ this.remaining[i] = rem;
+ }
+
+ void setShadow(int i, ByteBuffer buf) {
+ shadow[i] = buf;
+ }
+
+ ByteBuffer getBuffer(int i) {
+ return buf[i];
+ }
+
+ int getPosition(int i) {
+ return position[i];
+ }
+
+ int getRemaining(int i) {
+ return remaining[i];
+ }
+
+ ByteBuffer getShadow(int i) {
+ return shadow[i];
+ }
+
+ void clearRefs(int i) {
+ buf[i] = null;
+ shadow[i] = null;
}
void putBase(int i, long base) {
@@ -78,10 +154,6 @@
vecArray.putLong(offset, len);
}
- void free() {
- vecArray.free();
- }
-
static {
addressSize = Util.unsafe().addressSize();
LEN_OFFSET = addressSize;