View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.spdy;
20  
21  import java.nio.ByteBuffer;
22  import java.util.Queue;
23  import java.util.concurrent.ConcurrentHashMap;
24  import java.util.concurrent.ConcurrentLinkedQueue;
25  import java.util.concurrent.ConcurrentMap;
26  
27  public class StandardByteBufferPool implements ByteBufferPool
28  {
29      private final ConcurrentMap<Integer, Queue<ByteBuffer>> directBuffers = new ConcurrentHashMap<>();
30      private final ConcurrentMap<Integer, Queue<ByteBuffer>> heapBuffers = new ConcurrentHashMap<>();
31      private final int factor;
32  
33      public StandardByteBufferPool()
34      {
35          this(1024);
36      }
37  
38      public StandardByteBufferPool(int factor)
39      {
40          this.factor = factor;
41      }
42  
43      public ByteBuffer acquire(int size, boolean direct)
44      {
45          int bucket = bucketFor(size);
46          ConcurrentMap<Integer, Queue<ByteBuffer>> buffers = buffersFor(direct);
47  
48          ByteBuffer result = null;
49          Queue<ByteBuffer> byteBuffers = buffers.get(bucket);
50          if (byteBuffers != null)
51              result = byteBuffers.poll();
52  
53          if (result == null)
54          {
55              int capacity = bucket * factor;
56              result = direct ? ByteBuffer.allocateDirect(capacity) : ByteBuffer.allocate(capacity);
57          }
58  
59          result.clear();
60          result.limit(size);
61  
62          return result;
63      }
64  
65      public void release(ByteBuffer buffer)
66      {
67          int bucket = bucketFor(buffer.capacity());
68          ConcurrentMap<Integer, Queue<ByteBuffer>> buffers = buffersFor(buffer.isDirect());
69  
70          // Avoid to create a new queue every time, just to be discarded immediately
71          Queue<ByteBuffer> byteBuffers = buffers.get(bucket);
72          if (byteBuffers == null)
73          {
74              byteBuffers = new ConcurrentLinkedQueue<>();
75              Queue<ByteBuffer> existing = buffers.putIfAbsent(bucket, byteBuffers);
76              if (existing != null)
77                  byteBuffers = existing;
78          }
79  
80          buffer.clear();
81          byteBuffers.offer(buffer);
82      }
83  
84      public void clear()
85      {
86          directBuffers.clear();
87          heapBuffers.clear();
88      }
89  
90      private int bucketFor(int size)
91      {
92          int bucket = size / factor;
93          if (size % factor > 0)
94              ++bucket;
95          return bucket;
96      }
97  
98      private ConcurrentMap<Integer, Queue<ByteBuffer>> buffersFor(boolean direct)
99      {
100         return direct ? directBuffers : heapBuffers;
101     }
102 }