View Javadoc
1   /*
2    * Copyright 2013 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  /*
17   * Written by Josh Bloch of Google Inc. and released to the public domain,
18   * as explained at http://creativecommons.org/publicdomain/zero/1.0/.
19   */
20  package io.netty.channel;
21  
22  import io.netty.buffer.ByteBuf;
23  import io.netty.buffer.UnpooledByteBufAllocator;
24  import io.netty.buffer.UnpooledDirectByteBuf;
25  import io.netty.buffer.UnpooledUnsafeDirectByteBuf;
26  import io.netty.util.Recycler;
27  import io.netty.util.internal.PlatformDependent;
28  import io.netty.util.internal.SystemPropertyUtil;
29  import io.netty.util.internal.logging.InternalLogger;
30  import io.netty.util.internal.logging.InternalLoggerFactory;
31  
32  final class ThreadLocalPooledDirectByteBuf {
33      private static final InternalLogger logger =
34              InternalLoggerFactory.getInstance(ThreadLocalPooledDirectByteBuf.class);
35      public static final int threadLocalDirectBufferSize;
36  
37      static {
38          threadLocalDirectBufferSize = SystemPropertyUtil.getInt("io.netty.threadLocalDirectBufferSize", 64 * 1024);
39          logger.debug("-Dio.netty.threadLocalDirectBufferSize: {}", threadLocalDirectBufferSize);
40      }
41  
42      public static ByteBuf newInstance() {
43          if (PlatformDependent.hasUnsafe()) {
44              return ThreadLocalUnsafeDirectByteBuf.newInstance();
45          } else {
46              return ThreadLocalDirectByteBuf.newInstance();
47          }
48      }
49  
50      private ThreadLocalPooledDirectByteBuf() {
51          // utility
52      }
53  
54      static final class ThreadLocalUnsafeDirectByteBuf extends UnpooledUnsafeDirectByteBuf {
55  
56          private static final Recycler<ThreadLocalUnsafeDirectByteBuf> RECYCLER =
57                  new Recycler<ThreadLocalUnsafeDirectByteBuf>() {
58              @Override
59              protected ThreadLocalUnsafeDirectByteBuf newObject(Handle<ThreadLocalUnsafeDirectByteBuf> handle) {
60                  return new ThreadLocalUnsafeDirectByteBuf(handle);
61              }
62          };
63  
64          static ThreadLocalUnsafeDirectByteBuf newInstance() {
65              ThreadLocalUnsafeDirectByteBuf buf = RECYCLER.get();
66              buf.setRefCnt(1);
67              return buf;
68          }
69  
70          private final Recycler.Handle<ThreadLocalUnsafeDirectByteBuf> handle;
71  
72          private ThreadLocalUnsafeDirectByteBuf(Recycler.Handle<ThreadLocalUnsafeDirectByteBuf> handle) {
73              super(UnpooledByteBufAllocator.DEFAULT, 256, Integer.MAX_VALUE);
74              this.handle = handle;
75          }
76  
77          @Override
78          protected void deallocate() {
79              if (capacity() > threadLocalDirectBufferSize) {
80                  super.deallocate();
81              } else {
82                  clear();
83                  RECYCLER.recycle(this, handle);
84              }
85          }
86      }
87  
88      static final class ThreadLocalDirectByteBuf extends UnpooledDirectByteBuf {
89  
90          private static final Recycler<ThreadLocalDirectByteBuf> RECYCLER = new Recycler<ThreadLocalDirectByteBuf>() {
91              @Override
92              protected ThreadLocalDirectByteBuf newObject(Handle<ThreadLocalDirectByteBuf> handle) {
93                  return new ThreadLocalDirectByteBuf(handle);
94              }
95          };
96  
97          static ThreadLocalDirectByteBuf newInstance() {
98              ThreadLocalDirectByteBuf buf = RECYCLER.get();
99              buf.setRefCnt(1);
100             return buf;
101         }
102 
103         private final Recycler.Handle<ThreadLocalDirectByteBuf> handle;
104 
105         private ThreadLocalDirectByteBuf(Recycler.Handle<ThreadLocalDirectByteBuf> handle) {
106             super(UnpooledByteBufAllocator.DEFAULT, 256, Integer.MAX_VALUE);
107             this.handle = handle;
108         }
109 
110         @Override
111         protected void deallocate() {
112             if (capacity() > threadLocalDirectBufferSize) {
113                 super.deallocate();
114             } else {
115                 clear();
116                 RECYCLER.recycle(this, handle);
117             }
118         }
119     }
120 }