View Javadoc

1   /*
2    * Copyright (c) 2012 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * 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,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.eclipse.jetty.spdy;
18  
19  import java.nio.ByteBuffer;
20  import java.util.Queue;
21  import java.util.concurrent.ConcurrentHashMap;
22  import java.util.concurrent.ConcurrentLinkedQueue;
23  import java.util.concurrent.ConcurrentMap;
24  
25  public class StandardByteBufferPool implements ByteBufferPool
26  {
27      private final ConcurrentMap<Integer, Queue<ByteBuffer>> directBuffers = new ConcurrentHashMap<>();
28      private final ConcurrentMap<Integer, Queue<ByteBuffer>> heapBuffers = new ConcurrentHashMap<>();
29      private final int factor;
30  
31      public StandardByteBufferPool()
32      {
33          this(1024);
34      }
35  
36      public StandardByteBufferPool(int factor)
37      {
38          this.factor = factor;
39      }
40  
41      public ByteBuffer acquire(int size, boolean direct)
42      {
43          int bucket = bucketFor(size);
44          ConcurrentMap<Integer, Queue<ByteBuffer>> buffers = buffersFor(direct);
45  
46          ByteBuffer result = null;
47          Queue<ByteBuffer> byteBuffers = buffers.get(bucket);
48          if (byteBuffers != null)
49              result = byteBuffers.poll();
50  
51          if (result == null)
52          {
53              int capacity = bucket * factor;
54              result = direct ? ByteBuffer.allocateDirect(capacity) : ByteBuffer.allocate(capacity);
55          }
56  
57          result.clear();
58          result.limit(size);
59  
60          return result;
61      }
62  
63      public void release(ByteBuffer buffer)
64      {
65          int bucket = bucketFor(buffer.capacity());
66          ConcurrentMap<Integer, Queue<ByteBuffer>> buffers = buffersFor(buffer.isDirect());
67  
68          // Avoid to create a new queue every time, just to be discarded immediately
69          Queue<ByteBuffer> byteBuffers = buffers.get(bucket);
70          if (byteBuffers == null)
71          {
72              byteBuffers = new ConcurrentLinkedQueue<>();
73              Queue<ByteBuffer> existing = buffers.putIfAbsent(bucket, byteBuffers);
74              if (existing != null)
75                  byteBuffers = existing;
76          }
77  
78          buffer.clear();
79          byteBuffers.offer(buffer);
80      }
81  
82      public void clear()
83      {
84          directBuffers.clear();
85          heapBuffers.clear();
86      }
87  
88      private int bucketFor(int size)
89      {
90          int bucket = size / factor;
91          if (size % factor > 0)
92              ++bucket;
93          return bucket;
94      }
95  
96      private ConcurrentMap<Integer, Queue<ByteBuffer>> buffersFor(boolean direct)
97      {
98          return direct ? directBuffers : heapBuffers;
99      }
100 }