18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.nio.ch;
27
28 import java.io.FileDescriptor;
29 import java.lang.reflect.Constructor;
30 import java.lang.reflect.InvocationTargetException;
31 import java.nio.ByteBuffer;
32 import java.nio.MappedByteBuffer;
33 import java.security.AccessController;
34 import java.security.PrivilegedAction;
35 import java.util.Collection;
36 import java.util.Iterator;
37 import java.util.Set;
38 import jdk.internal.misc.Unsafe;
39 import sun.security.action.GetPropertyAction;
40 import java.io.IOException;
41
42 public class Util {
43
44 // -- Caches --
45
46 // The number of temp buffers in our pool
47 private static final int TEMP_BUF_POOL_SIZE = IOUtil.IOV_MAX;
48
49 // The max size allowed for a cached temp buffer, in bytes
50 private static final long MAX_CACHED_BUFFER_SIZE = getMaxCachedBufferSize();
51
52 // Per-thread cache of temporary direct buffers
53 private static ThreadLocal<BufferCache> bufferCache =
54 new ThreadLocal<BufferCache>()
55 {
56 @Override
57 protected BufferCache initialValue() {
58 return new BufferCache();
59 }
60 };
61
62 /**
63 * Returns the max size allowed for a cached temp buffers, in
64 * bytes. It defaults to Long.MAX_VALUE. It can be set with the
65 * jdk.nio.maxCachedBufferSize property. Even though
66 * ByteBuffer.capacity() returns an int, we're using a long here
67 * for potential future-proofing.
68 */
69 private static long getMaxCachedBufferSize() {
70 String s = GetPropertyAction
71 .privilegedGetProperty("jdk.nio.maxCachedBufferSize");
72 if (s != null) {
73 try {
74 long m = Long.parseLong(s);
75 if (m >= 0) {
76 return m;
77 } else {
78 // if it's negative, ignore the system property
79 }
188 } else {
189 int next = (start + count) % TEMP_BUF_POOL_SIZE;
190 buffers[next] = buf;
191 count++;
192 return true;
193 }
194 }
195
196 boolean isEmpty() {
197 return count == 0;
198 }
199
200 ByteBuffer removeFirst() {
201 assert count > 0;
202 ByteBuffer buf = buffers[start];
203 buffers[start] = null;
204 start = next(start);
205 count--;
206 return buf;
207 }
208 }
209
210 /**
211 * Returns a temporary buffer of at least the given size
212 */
213 public static ByteBuffer getTemporaryDirectBuffer(int size) {
214 // If a buffer of this size is too large for the cache, there
215 // should not be a buffer in the cache that is at least as
216 // large. So we'll just create a new one. Also, we don't have
217 // to remove the buffer from the cache (as this method does
218 // below) given that we won't put the new buffer in the cache.
219 if (isBufferTooLarge(size)) {
220 return ByteBuffer.allocateDirect(size);
221 }
222
223 BufferCache cache = bufferCache.get();
224 ByteBuffer buf = cache.get(size);
225 if (buf != null) {
226 return buf;
227 } else {
|
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.nio.ch;
27
28 import java.io.FileDescriptor;
29 import java.lang.reflect.Constructor;
30 import java.lang.reflect.InvocationTargetException;
31 import java.nio.ByteBuffer;
32 import java.nio.MappedByteBuffer;
33 import java.security.AccessController;
34 import java.security.PrivilegedAction;
35 import java.util.Collection;
36 import java.util.Iterator;
37 import java.util.Set;
38 import jdk.internal.misc.JdkThreadLocal;
39 import jdk.internal.misc.Unsafe;
40 import sun.security.action.GetPropertyAction;
41 import java.io.IOException;
42
43 public class Util {
44
45 // -- Caches --
46
47 // The number of temp buffers in our pool
48 private static final int TEMP_BUF_POOL_SIZE = IOUtil.IOV_MAX;
49
50 // The max size allowed for a cached temp buffer, in bytes
51 private static final long MAX_CACHED_BUFFER_SIZE = getMaxCachedBufferSize();
52
53 // Per-thread cache of temporary direct buffers
54 private static ThreadLocal<BufferCache> bufferCache =
55 new JdkThreadLocal<>()
56 {
57 @Override
58 protected BufferCache initialValue() {
59 return new BufferCache();
60 }
61
62 @Override
63 protected void threadTerminated(BufferCache cache) {
64 cache.freeAll();
65 }
66 };
67
68 /**
69 * Returns the max size allowed for a cached temp buffers, in
70 * bytes. It defaults to Long.MAX_VALUE. It can be set with the
71 * jdk.nio.maxCachedBufferSize property. Even though
72 * ByteBuffer.capacity() returns an int, we're using a long here
73 * for potential future-proofing.
74 */
75 private static long getMaxCachedBufferSize() {
76 String s = GetPropertyAction
77 .privilegedGetProperty("jdk.nio.maxCachedBufferSize");
78 if (s != null) {
79 try {
80 long m = Long.parseLong(s);
81 if (m >= 0) {
82 return m;
83 } else {
84 // if it's negative, ignore the system property
85 }
194 } else {
195 int next = (start + count) % TEMP_BUF_POOL_SIZE;
196 buffers[next] = buf;
197 count++;
198 return true;
199 }
200 }
201
202 boolean isEmpty() {
203 return count == 0;
204 }
205
206 ByteBuffer removeFirst() {
207 assert count > 0;
208 ByteBuffer buf = buffers[start];
209 buffers[start] = null;
210 start = next(start);
211 count--;
212 return buf;
213 }
214
215 void freeAll() {
216 if (isEmpty()) {
217 return;
218 }
219
220 for (int i = 0; i < buffers.length; i += 1) {
221 final ByteBuffer buf = buffers[i];
222 if (buf == null) {
223 continue;
224 }
225
226 free(buf);
227 // just in case
228 buffers[i] = null;
229 }
230 // just in case
231 count = 0;
232 }
233 }
234
235 /**
236 * Returns a temporary buffer of at least the given size
237 */
238 public static ByteBuffer getTemporaryDirectBuffer(int size) {
239 // If a buffer of this size is too large for the cache, there
240 // should not be a buffer in the cache that is at least as
241 // large. So we'll just create a new one. Also, we don't have
242 // to remove the buffer from the cache (as this method does
243 // below) given that we won't put the new buffer in the cache.
244 if (isBufferTooLarge(size)) {
245 return ByteBuffer.allocateDirect(size);
246 }
247
248 BufferCache cache = bufferCache.get();
249 ByteBuffer buf = cache.get(size);
250 if (buf != null) {
251 return buf;
252 } else {
|