1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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(0,1024,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 if (buffer!=null)
79 {
80 Bucket bucket = bucketFor(buffer.capacity(),buffer.isDirect());
81 if (bucket!=null)
82 {
83 BufferUtil.clear(buffer);
84 bucket._queue.offer(buffer);
85 }
86 }
87 }
88
89 public void clear()
90 {
91 for (int i=0;i<_direct.length;i++)
92 {
93 _direct[i]._queue.clear();
94 _indirect[i]._queue.clear();
95 }
96 }
97
98 private Bucket bucketFor(int size,boolean direct)
99 {
100 if (size<=_min)
101 return null;
102 int b=(size-1)/_inc;
103 if (b>=_direct.length)
104 return null;
105 Bucket bucket = direct?_direct[b]:_indirect[b];
106
107 return bucket;
108 }
109
110 public static class Bucket
111 {
112 public final int _size;
113 public final Queue<ByteBuffer> _queue= new ConcurrentLinkedQueue<>();
114
115 Bucket(int size)
116 {
117 _size=size;
118 }
119
120 @Override
121 public String toString()
122 {
123 return String.format("Bucket@%x{%d,%d}",hashCode(),_size,_queue.size());
124 }
125 }
126
127
128
129 Bucket[] bucketsFor(boolean direct)
130 {
131 return direct ? _direct : _indirect;
132 }
133 }