< prev index next >

src/java.base/share/classes/sun/nio/ch/Util.java

Print this page




  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.io.IOException;
  30 import java.lang.reflect.Constructor;
  31 import java.lang.reflect.InvocationTargetException;
  32 import java.nio.ByteBuffer;
  33 import java.nio.MappedByteBuffer;
  34 import java.security.AccessController;
  35 import java.security.PrivilegedAction;
  36 import java.util.Collection;
  37 import java.util.Iterator;
  38 import java.util.Set;
  39 


  40 import jdk.internal.misc.TerminatingThreadLocal;
  41 import jdk.internal.misc.Unsafe;
  42 import sun.security.action.GetPropertyAction;
  43 
  44 public class Util {

  45 
  46     // -- Caches --
  47 
  48     // The number of temp buffers in our pool
  49     private static final int TEMP_BUF_POOL_SIZE = IOUtil.IOV_MAX;
  50 
  51     // The max size allowed for a cached temp buffer, in bytes
  52     private static final long MAX_CACHED_BUFFER_SIZE = getMaxCachedBufferSize();
  53 
  54     // Per-thread cache of temporary direct buffers
  55     private static ThreadLocal<BufferCache> bufferCache = new TerminatingThreadLocal<>() {
  56         @Override
  57         protected BufferCache initialValue() {
  58             return new BufferCache();
  59         }
  60         @Override
  61         protected void threadTerminated(BufferCache cache) { // will never be null
  62             while (!cache.isEmpty()) {
  63                 ByteBuffer bb = cache.removeFirst();
  64                 free(bb);


 210             buffers[start] = null;
 211             start = next(start);
 212             count--;
 213             return buf;
 214         }
 215     }
 216 
 217     /**
 218      * Returns a temporary buffer of at least the given size
 219      */
 220     public static ByteBuffer getTemporaryDirectBuffer(int size) {
 221         // If a buffer of this size is too large for the cache, there
 222         // should not be a buffer in the cache that is at least as
 223         // large. So we'll just create a new one. Also, we don't have
 224         // to remove the buffer from the cache (as this method does
 225         // below) given that we won't put the new buffer in the cache.
 226         if (isBufferTooLarge(size)) {
 227             return ByteBuffer.allocateDirect(size);
 228         }
 229 
 230         BufferCache cache = bufferCache.get();
 231         ByteBuffer buf = cache.get(size);
 232         if (buf != null) {
 233             return buf;
 234         } else {
 235             // No suitable buffer in the cache so we need to allocate a new
 236             // one. To avoid the cache growing then we remove the first
 237             // buffer from the cache and free it.
 238             if (!cache.isEmpty()) {
 239                 buf = cache.removeFirst();
 240                 free(buf);
 241             }
 242             return ByteBuffer.allocateDirect(size);
 243         }
 244     }
 245 
 246     /**
 247      * Returns a temporary buffer of at least the given size and
 248      * aligned to the alignment
 249      */
 250     public static ByteBuffer getTemporaryAlignedDirectBuffer(int size,
 251                                                              int alignment) {
 252         if (isBufferTooLarge(size)) {
 253             return ByteBuffer.allocateDirect(size + alignment - 1)
 254                     .alignedSlice(alignment);
 255         }
 256 
 257         BufferCache cache = bufferCache.get();
 258         ByteBuffer buf = cache.get(size);
 259         if (buf != null) {
 260             if (buf.alignmentOffset(0, alignment) == 0) {
 261                 return buf;
 262             }
 263         } else {
 264             if (!cache.isEmpty()) {
 265                 buf = cache.removeFirst();
 266                 free(buf);
 267             }
 268         }
 269         return ByteBuffer.allocateDirect(size + alignment - 1)
 270                 .alignedSlice(alignment);
 271     }
 272 
 273     /**
 274      * Releases a temporary buffer by returning to the cache or freeing it.
 275      */
 276     public static void releaseTemporaryDirectBuffer(ByteBuffer buf) {
 277         offerFirstTemporaryDirectBuffer(buf);
 278     }
 279 
 280     /**
 281      * Releases a temporary buffer by returning to the cache or freeing it. If
 282      * returning to the cache then insert it at the start so that it is
 283      * likely to be returned by a subsequent call to getTemporaryDirectBuffer.
 284      */
 285     static void offerFirstTemporaryDirectBuffer(ByteBuffer buf) {
 286         // If the buffer is too large for the cache we don't have to
 287         // check the cache. We'll just free it.
 288         if (isBufferTooLarge(buf)) {
 289             free(buf);
 290             return;
 291         }
 292 
 293         assert buf != null;
 294         BufferCache cache = bufferCache.get();
 295         if (!cache.offerFirst(buf)) {
 296             // cache is full
 297             free(buf);
 298         }
 299     }
 300 
 301     /**
 302      * Releases a temporary buffer by returning to the cache or freeing it. If
 303      * returning to the cache then insert it at the end. This makes it
 304      * suitable for scatter/gather operations where the buffers are returned to
 305      * cache in same order that they were obtained.
 306      */
 307     static void offerLastTemporaryDirectBuffer(ByteBuffer buf) {
 308         // If the buffer is too large for the cache we don't have to
 309         // check the cache. We'll just free it.
 310         if (isBufferTooLarge(buf)) {
 311             free(buf);
 312             return;
 313         }
 314 
 315         assert buf != null;
 316         BufferCache cache = bufferCache.get();
 317         if (!cache.offerLast(buf)) {
 318             // cache is full
 319             free(buf);
 320         }
 321     }
 322 
 323     /**
 324      * Frees the memory for the given direct buffer
 325      */
 326     private static void free(ByteBuffer buf) {
 327         ((DirectBuffer)buf).cleaner().clean();
 328     }
 329 
 330 
 331     // -- Random stuff --
 332 
 333     static ByteBuffer[] subsequence(ByteBuffer[] bs, int offset, int length) {
 334         if ((offset == 0) && (length == bs.length))
 335             return bs;
 336         int n = length;




  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.io.IOException;
  30 import java.lang.reflect.Constructor;
  31 import java.lang.reflect.InvocationTargetException;
  32 import java.nio.ByteBuffer;
  33 import java.nio.MappedByteBuffer;
  34 import java.security.AccessController;
  35 import java.security.PrivilegedAction;
  36 import java.util.Collection;
  37 import java.util.Iterator;
  38 import java.util.Set;
  39 
  40 import jdk.internal.access.JavaLangAccess;
  41 import jdk.internal.access.SharedSecrets;
  42 import jdk.internal.misc.TerminatingThreadLocal;
  43 import jdk.internal.misc.Unsafe;
  44 import sun.security.action.GetPropertyAction;
  45 
  46 public class Util {
  47     private static JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
  48 
  49     // -- Caches --
  50 
  51     // The number of temp buffers in our pool
  52     private static final int TEMP_BUF_POOL_SIZE = IOUtil.IOV_MAX;
  53 
  54     // The max size allowed for a cached temp buffer, in bytes
  55     private static final long MAX_CACHED_BUFFER_SIZE = getMaxCachedBufferSize();
  56 
  57     // Per-thread cache of temporary direct buffers
  58     private static ThreadLocal<BufferCache> bufferCache = new TerminatingThreadLocal<>() {
  59         @Override
  60         protected BufferCache initialValue() {
  61             return new BufferCache();
  62         }
  63         @Override
  64         protected void threadTerminated(BufferCache cache) { // will never be null
  65             while (!cache.isEmpty()) {
  66                 ByteBuffer bb = cache.removeFirst();
  67                 free(bb);


 213             buffers[start] = null;
 214             start = next(start);
 215             count--;
 216             return buf;
 217         }
 218     }
 219 
 220     /**
 221      * Returns a temporary buffer of at least the given size
 222      */
 223     public static ByteBuffer getTemporaryDirectBuffer(int size) {
 224         // If a buffer of this size is too large for the cache, there
 225         // should not be a buffer in the cache that is at least as
 226         // large. So we'll just create a new one. Also, we don't have
 227         // to remove the buffer from the cache (as this method does
 228         // below) given that we won't put the new buffer in the cache.
 229         if (isBufferTooLarge(size)) {
 230             return ByteBuffer.allocateDirect(size);
 231         }
 232 
 233         BufferCache cache = JLA.getCarrierThreadLocal(bufferCache);
 234         ByteBuffer buf = cache.get(size);
 235         if (buf != null) {
 236             return buf;
 237         } else {
 238             // No suitable buffer in the cache so we need to allocate a new
 239             // one. To avoid the cache growing then we remove the first
 240             // buffer from the cache and free it.
 241             if (!cache.isEmpty()) {
 242                 buf = cache.removeFirst();
 243                 free(buf);
 244             }
 245             return ByteBuffer.allocateDirect(size);
 246         }
 247     }
 248 
 249     /**
 250      * Returns a temporary buffer of at least the given size and
 251      * aligned to the alignment
 252      */
 253     public static ByteBuffer getTemporaryAlignedDirectBuffer(int size,
 254                                                              int alignment) {
 255         if (isBufferTooLarge(size)) {
 256             return ByteBuffer.allocateDirect(size + alignment - 1)
 257                     .alignedSlice(alignment);
 258         }
 259 
 260         BufferCache cache = JLA.getCarrierThreadLocal(bufferCache);
 261         ByteBuffer buf = cache.get(size);
 262         if (buf != null) {
 263             if (buf.alignmentOffset(0, alignment) == 0) {
 264                 return buf;
 265             }
 266         } else {
 267             if (!cache.isEmpty()) {
 268                 buf = cache.removeFirst();
 269                 free(buf);
 270             }
 271         }
 272         return ByteBuffer.allocateDirect(size + alignment - 1)
 273                 .alignedSlice(alignment);
 274     }
 275 
 276     /**
 277      * Releases a temporary buffer by returning to the cache or freeing it.
 278      */
 279     public static void releaseTemporaryDirectBuffer(ByteBuffer buf) {
 280         offerFirstTemporaryDirectBuffer(buf);
 281     }
 282 
 283     /**
 284      * Releases a temporary buffer by returning to the cache or freeing it. If
 285      * returning to the cache then insert it at the start so that it is
 286      * likely to be returned by a subsequent call to getTemporaryDirectBuffer.
 287      */
 288     static void offerFirstTemporaryDirectBuffer(ByteBuffer buf) {
 289         // If the buffer is too large for the cache we don't have to
 290         // check the cache. We'll just free it.
 291         if (isBufferTooLarge(buf)) {
 292             free(buf);
 293             return;
 294         }
 295 
 296         assert buf != null;
 297         BufferCache cache = JLA.getCarrierThreadLocal(bufferCache);
 298         if (!cache.offerFirst(buf)) {
 299             // cache is full
 300             free(buf);
 301         }
 302     }
 303 
 304     /**
 305      * Releases a temporary buffer by returning to the cache or freeing it. If
 306      * returning to the cache then insert it at the end. This makes it
 307      * suitable for scatter/gather operations where the buffers are returned to
 308      * cache in same order that they were obtained.
 309      */
 310     static void offerLastTemporaryDirectBuffer(ByteBuffer buf) {
 311         // If the buffer is too large for the cache we don't have to
 312         // check the cache. We'll just free it.
 313         if (isBufferTooLarge(buf)) {
 314             free(buf);
 315             return;
 316         }
 317 
 318         assert buf != null;
 319         BufferCache cache = JLA.getCarrierThreadLocal(bufferCache);
 320         if (!cache.offerLast(buf)) {
 321             // cache is full
 322             free(buf);
 323         }
 324     }
 325 
 326     /**
 327      * Frees the memory for the given direct buffer
 328      */
 329     private static void free(ByteBuffer buf) {
 330         ((DirectBuffer)buf).cleaner().clean();
 331     }
 332 
 333 
 334     // -- Random stuff --
 335 
 336     static ByteBuffer[] subsequence(ByteBuffer[] bs, int offset, int length) {
 337         if ((offset == 0) && (length == bs.length))
 338             return bs;
 339         int n = length;


< prev index next >