41 */ |
42 */ |
42 |
43 |
43 class IOVecWrapper { |
44 class IOVecWrapper { |
44 |
45 |
45 // Miscellaneous constants |
46 // Miscellaneous constants |
46 static int BASE_OFFSET = 0; |
47 private static final int BASE_OFFSET = 0; |
47 static int LEN_OFFSET; |
48 private static final int LEN_OFFSET; |
48 static int SIZE_IOVEC; |
49 private static final int SIZE_IOVEC; |
49 |
50 |
50 // The iovec array |
51 // The iovec array |
51 private AllocatedNativeObject vecArray; |
52 private final AllocatedNativeObject vecArray; |
|
53 |
|
54 // Number of elements in iovec array |
|
55 private final int size; |
|
56 |
|
57 // Buffers and position/remaining corresponding to elements in iovec array |
|
58 private final ByteBuffer[] buf; |
|
59 private final int[] position; |
|
60 private final int[] remaining; |
|
61 |
|
62 // Shadow buffers for cases when original buffer is substituted |
|
63 private final ByteBuffer[] shadow; |
52 |
64 |
53 // Base address of this array |
65 // Base address of this array |
54 long address; |
66 final long address; |
55 |
67 |
56 // Address size in bytes |
68 // Address size in bytes |
57 static int addressSize; |
69 static int addressSize; |
58 |
70 |
59 IOVecWrapper(int newSize) { |
71 private static class Deallocator implements Runnable { |
60 newSize = (newSize + 1) * SIZE_IOVEC; |
72 private final AllocatedNativeObject obj; |
61 vecArray = new AllocatedNativeObject(newSize, false); |
73 Deallocator(AllocatedNativeObject obj) { |
62 address = vecArray.address(); |
74 this.obj = obj; |
|
75 } |
|
76 public void run() { |
|
77 obj.free(); |
|
78 } |
|
79 } |
|
80 |
|
81 // per thread IOVecWrapper |
|
82 private static final ThreadLocal<IOVecWrapper> cached = |
|
83 new ThreadLocal<IOVecWrapper>(); |
|
84 |
|
85 private IOVecWrapper(int size) { |
|
86 this.size = size; |
|
87 this.buf = new ByteBuffer[size]; |
|
88 this.position = new int[size]; |
|
89 this.remaining = new int[size]; |
|
90 this.shadow = new ByteBuffer[size]; |
|
91 this.vecArray = new AllocatedNativeObject(size * SIZE_IOVEC, false); |
|
92 this.address = vecArray.address(); |
|
93 } |
|
94 |
|
95 static IOVecWrapper get(int size) { |
|
96 IOVecWrapper wrapper = cached.get(); |
|
97 if (wrapper != null && wrapper.size < size) { |
|
98 // not big enough; eagerly release memory |
|
99 wrapper.vecArray.free(); |
|
100 wrapper = null; |
|
101 } |
|
102 if (wrapper == null) { |
|
103 wrapper = new IOVecWrapper(size); |
|
104 Cleaner.create(wrapper, new Deallocator(wrapper.vecArray)); |
|
105 cached.set(wrapper); |
|
106 } |
|
107 return wrapper; |
|
108 } |
|
109 |
|
110 void setBuffer(int i, ByteBuffer buf, int pos, int rem) { |
|
111 this.buf[i] = buf; |
|
112 this.position[i] = pos; |
|
113 this.remaining[i] = rem; |
|
114 } |
|
115 |
|
116 void setShadow(int i, ByteBuffer buf) { |
|
117 shadow[i] = buf; |
|
118 } |
|
119 |
|
120 ByteBuffer getBuffer(int i) { |
|
121 return buf[i]; |
|
122 } |
|
123 |
|
124 int getPosition(int i) { |
|
125 return position[i]; |
|
126 } |
|
127 |
|
128 int getRemaining(int i) { |
|
129 return remaining[i]; |
|
130 } |
|
131 |
|
132 ByteBuffer getShadow(int i) { |
|
133 return shadow[i]; |
|
134 } |
|
135 |
|
136 void clearRefs(int i) { |
|
137 buf[i] = null; |
|
138 shadow[i] = null; |
63 } |
139 } |
64 |
140 |
65 void putBase(int i, long base) { |
141 void putBase(int i, long base) { |
66 int offset = SIZE_IOVEC * i + BASE_OFFSET; |
142 int offset = SIZE_IOVEC * i + BASE_OFFSET; |
67 if (addressSize == 4) |
143 if (addressSize == 4) |