View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2012 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.io;
20  
21  import java.nio.ByteBuffer;
22  import java.util.Queue;
23  import java.util.concurrent.ConcurrentLinkedQueue;
24  
25  import org.eclipse.jetty.util.BufferUtil;
26  
27  public class ArrayByteBufferPool implements ByteBufferPool
28  {
29      private final int _min;
30      private final Bucket[] _direct;
31      private final Bucket[] _indirect;
32      private final int _inc;
33  
34      public ArrayByteBufferPool()
35      {
36          this(64,2048,64*1024);
37      }
38  
39      public ArrayByteBufferPool(int minSize, int increment, int maxSize)
40      {
41          if (minSize>=increment)
42              throw new IllegalArgumentException("minSize >= increment");
43          if ((maxSize%increment)!=0 || increment>=maxSize)
44              throw new IllegalArgumentException("increment must be a divisor of maxSize");
45          _min=minSize;
46          _inc=increment;
47  
48          _direct=new Bucket[maxSize/increment];
49          _indirect=new Bucket[maxSize/increment];
50  
51          int size=0;
52          for (int i=0;i<_direct.length;i++)
53          {
54              size+=_inc;
55              _direct[i]=new Bucket(size);
56              _indirect[i]=new Bucket(size);
57          }
58      }
59  
60      @Override
61      public ByteBuffer acquire(int size, boolean direct)
62      {
63          Bucket bucket = bucketFor(size,direct);
64          ByteBuffer buffer = bucket==null?null:bucket._queue.poll();
65  
66          if (buffer == null)
67          {
68              int capacity = bucket==null?size:bucket._size;
69              buffer = direct ? BufferUtil.allocateDirect(capacity) : BufferUtil.allocate(capacity);
70          }
71  
72          return buffer;
73      }
74  
75      @Override
76      public void release(ByteBuffer buffer)
77      {
78          Bucket bucket = bucketFor(buffer.capacity(),buffer.isDirect());
79          if (bucket!=null)
80          {
81              BufferUtil.clear(buffer);
82              bucket._queue.offer(buffer);
83          }
84      }
85  
86      public void clear()
87      {
88          for (int i=0;i<_direct.length;i++)
89          {
90              _direct[i]._queue.clear();
91              _indirect[i]._queue.clear();
92          }
93      }
94  
95      private Bucket bucketFor(int size,boolean direct)
96      {
97          if (size<=_min)
98              return null;
99          int b=(size-1)/_inc;
100         if (b>=_direct.length)
101             return null;
102         Bucket bucket = direct?_direct[b]:_indirect[b];
103                 
104         return bucket;
105     }
106 
107     public static class Bucket
108     {
109         public final int _size;
110         public final Queue<ByteBuffer> _queue= new ConcurrentLinkedQueue<>();
111 
112         Bucket(int size)
113         {
114             _size=size;
115         }
116         
117         @Override
118         public String toString()
119         {
120             return String.format("Bucket@%x{%d,%d}",hashCode(),_size,_queue.size());
121         }
122     }
123     
124 
125     // Package local for testing
126     Bucket[] bucketsFor(boolean direct)
127     {
128         return direct ? _direct : _indirect;
129     }
130 }