47 |
47 |
48 // The number of temp buffers in our pool |
48 // The number of temp buffers in our pool |
49 private static final int TEMP_BUF_POOL_SIZE = 3; |
49 private static final int TEMP_BUF_POOL_SIZE = 3; |
50 |
50 |
51 // Per-thread soft cache of the last temporary direct buffer |
51 // Per-thread soft cache of the last temporary direct buffer |
52 private static ThreadLocal[] bufferPool; |
52 private static ThreadLocal<SoftReference<ByteBuffer>>[] bufferPool; |
53 |
53 |
54 static { |
54 static { |
55 bufferPool = new ThreadLocal[TEMP_BUF_POOL_SIZE]; |
55 bufferPool = (ThreadLocal<SoftReference<ByteBuffer>>[]) |
|
56 new ThreadLocal[TEMP_BUF_POOL_SIZE]; |
56 for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) |
57 for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) |
57 bufferPool[i] = new ThreadLocal(); |
58 bufferPool[i] = new ThreadLocal<SoftReference<ByteBuffer>>(); |
58 } |
59 } |
59 |
60 |
60 static ByteBuffer getTemporaryDirectBuffer(int size) { |
61 static ByteBuffer getTemporaryDirectBuffer(int size) { |
61 ByteBuffer buf = null; |
62 ByteBuffer buf = null; |
62 // Grab a buffer if available |
63 // Grab a buffer if available |
63 for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) { |
64 for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) { |
64 SoftReference ref = (SoftReference)(bufferPool[i].get()); |
65 SoftReference<ByteBuffer> ref = bufferPool[i].get(); |
65 if ((ref != null) && ((buf = (ByteBuffer)ref.get()) != null) && |
66 if ((ref != null) && ((buf = ref.get()) != null) && |
66 (buf.capacity() >= size)) { |
67 (buf.capacity() >= size)) { |
67 buf.rewind(); |
68 buf.rewind(); |
68 buf.limit(size); |
69 buf.limit(size); |
69 bufferPool[i].set(null); |
70 bufferPool[i].set(null); |
70 return buf; |
71 return buf; |
78 static void releaseTemporaryDirectBuffer(ByteBuffer buf) { |
79 static void releaseTemporaryDirectBuffer(ByteBuffer buf) { |
79 if (buf == null) |
80 if (buf == null) |
80 return; |
81 return; |
81 // Put it in an empty slot if such exists |
82 // Put it in an empty slot if such exists |
82 for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) { |
83 for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) { |
83 SoftReference ref = (SoftReference)(bufferPool[i].get()); |
84 SoftReference<ByteBuffer> ref = bufferPool[i].get(); |
84 if ((ref == null) || (ref.get() == null)) { |
85 if ((ref == null) || (ref.get() == null)) { |
85 bufferPool[i].set(new SoftReference(buf)); |
86 bufferPool[i].set(new SoftReference<ByteBuffer>(buf)); |
86 return; |
87 return; |
87 } |
88 } |
88 } |
89 } |
89 // Otherwise replace a smaller one in the cache if such exists |
90 // Otherwise replace a smaller one in the cache if such exists |
90 for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) { |
91 for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) { |
91 SoftReference ref = (SoftReference)(bufferPool[i].get()); |
92 SoftReference<ByteBuffer> ref = bufferPool[i].get(); |
92 ByteBuffer inCacheBuf = (ByteBuffer)ref.get(); |
93 ByteBuffer inCacheBuf = ref.get(); |
93 if ((inCacheBuf == null) || (buf.capacity() > inCacheBuf.capacity())) { |
94 if ((inCacheBuf == null) || (buf.capacity() > inCacheBuf.capacity())) { |
94 bufferPool[i].set(new SoftReference(buf)); |
95 bufferPool[i].set(new SoftReference<ByteBuffer>(buf)); |
95 return; |
96 return; |
96 } |
97 } |
97 } |
98 } |
98 } |
99 } |
99 |
100 |
118 } |
119 } |
119 public Selector get() { return sel;} |
120 public Selector get() { return sel;} |
120 } |
121 } |
121 |
122 |
122 // Per-thread cached selector |
123 // Per-thread cached selector |
123 private static ThreadLocal localSelector = new ThreadLocal(); |
124 private static ThreadLocal<SoftReference<SelectorWrapper>> localSelector |
|
125 = new ThreadLocal<SoftReference<SelectorWrapper>>(); |
124 // Hold a reference to the selWrapper object to prevent it from |
126 // Hold a reference to the selWrapper object to prevent it from |
125 // being cleaned when the temporary selector wrapped is on lease. |
127 // being cleaned when the temporary selector wrapped is on lease. |
126 private static ThreadLocal localSelectorWrapper = new ThreadLocal(); |
128 private static ThreadLocal<SelectorWrapper> localSelectorWrapper |
|
129 = new ThreadLocal<SelectorWrapper>(); |
127 |
130 |
128 // When finished, invoker must ensure that selector is empty |
131 // When finished, invoker must ensure that selector is empty |
129 // by cancelling any related keys and explicitly releasing |
132 // by cancelling any related keys and explicitly releasing |
130 // the selector by invoking releaseTemporarySelector() |
133 // the selector by invoking releaseTemporarySelector() |
131 static Selector getTemporarySelector(SelectableChannel sc) |
134 static Selector getTemporarySelector(SelectableChannel sc) |
132 throws IOException |
135 throws IOException |
133 { |
136 { |
134 SoftReference ref = (SoftReference)localSelector.get(); |
137 SoftReference<SelectorWrapper> ref = localSelector.get(); |
135 SelectorWrapper selWrapper = null; |
138 SelectorWrapper selWrapper = null; |
136 Selector sel = null; |
139 Selector sel = null; |
137 if (ref == null |
140 if (ref == null |
138 || ((selWrapper = (SelectorWrapper) ref.get()) == null) |
141 || ((selWrapper = ref.get()) == null) |
139 || ((sel = selWrapper.get()) == null) |
142 || ((sel = selWrapper.get()) == null) |
140 || (sel.provider() != sc.provider())) { |
143 || (sel.provider() != sc.provider())) { |
141 sel = sc.provider().openSelector(); |
144 sel = sc.provider().openSelector(); |
142 localSelector.set(new SoftReference(new SelectorWrapper(sel))); |
145 localSelector.set(new SoftReference<SelectorWrapper>( |
|
146 new SelectorWrapper(sel))); |
143 } else { |
147 } else { |
144 localSelectorWrapper.set(selWrapper); |
148 localSelectorWrapper.set(selWrapper); |
145 } |
149 } |
146 return sel; |
150 return sel; |
147 } |
151 } |
233 } |
237 } |
234 |
238 |
235 private static volatile Constructor directByteBufferConstructor = null; |
239 private static volatile Constructor directByteBufferConstructor = null; |
236 |
240 |
237 private static void initDBBConstructor() { |
241 private static void initDBBConstructor() { |
238 AccessController.doPrivileged(new PrivilegedAction() { |
242 AccessController.doPrivileged(new PrivilegedAction<Void>() { |
239 public Object run() { |
243 public Void run() { |
240 try { |
244 try { |
241 Class cl = Class.forName("java.nio.DirectByteBuffer"); |
245 Class<?> cl = Class.forName("java.nio.DirectByteBuffer"); |
242 Constructor ctor = cl.getDeclaredConstructor( |
246 Constructor ctor = cl.getDeclaredConstructor( |
243 new Class[] { int.class, |
247 new Class[] { int.class, |
244 long.class, |
248 long.class, |
245 Runnable.class }); |
249 Runnable.class }); |
246 ctor.setAccessible(true); |
250 ctor.setAccessible(true); |
280 } |
284 } |
281 |
285 |
282 private static volatile Constructor directByteBufferRConstructor = null; |
286 private static volatile Constructor directByteBufferRConstructor = null; |
283 |
287 |
284 private static void initDBBRConstructor() { |
288 private static void initDBBRConstructor() { |
285 AccessController.doPrivileged(new PrivilegedAction() { |
289 AccessController.doPrivileged(new PrivilegedAction<Void>() { |
286 public Object run() { |
290 public Void run() { |
287 try { |
291 try { |
288 Class cl = Class.forName("java.nio.DirectByteBufferR"); |
292 Class<?> cl = Class.forName("java.nio.DirectByteBufferR"); |
289 Constructor ctor = cl.getDeclaredConstructor( |
293 Constructor ctor = cl.getDeclaredConstructor( |
290 new Class[] { int.class, |
294 new Class[] { int.class, |
291 long.class, |
295 long.class, |
292 Runnable.class }); |
296 Runnable.class }); |
293 ctor.setAccessible(true); |
297 ctor.setAccessible(true); |