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.ArrayList;
23 import java.util.List;
24 import java.util.Queue;
25 import java.util.concurrent.atomic.AtomicInteger;
26
27 import org.eclipse.jetty.util.BufferUtil;
28 import org.eclipse.jetty.util.ConcurrentArrayQueue;
29
30
31
32
33
34
35
36 public interface ByteBufferPool
37 {
38
39
40
41
42
43
44
45
46
47
48 public ByteBuffer acquire(int size, boolean direct);
49
50
51
52
53
54
55
56
57 public void release(ByteBuffer buffer);
58
59 default ByteBuffer newByteBuffer(int capacity, boolean direct)
60 {
61 return direct ? BufferUtil.allocateDirect(capacity) : BufferUtil.allocate(capacity);
62 }
63
64 public static class Lease
65 {
66 private final ByteBufferPool byteBufferPool;
67 private final List<ByteBuffer> buffers;
68 private final List<Boolean> recycles;
69
70 public Lease(ByteBufferPool byteBufferPool)
71 {
72 this.byteBufferPool = byteBufferPool;
73 this.buffers = new ArrayList<>();
74 this.recycles = new ArrayList<>();
75 }
76
77 public ByteBuffer acquire(int capacity, boolean direct)
78 {
79 ByteBuffer buffer = byteBufferPool.acquire(capacity, direct);
80 BufferUtil.clearToFill(buffer);
81 return buffer;
82 }
83
84 public void append(ByteBuffer buffer, boolean recycle)
85 {
86 buffers.add(buffer);
87 recycles.add(recycle);
88 }
89
90 public void insert(int index, ByteBuffer buffer, boolean recycle)
91 {
92 buffers.add(index, buffer);
93 recycles.add(index, recycle);
94 }
95
96 public List<ByteBuffer> getByteBuffers()
97 {
98 return buffers;
99 }
100
101 public long getTotalLength()
102 {
103 long length = 0;
104 for (int i = 0; i < buffers.size(); ++i)
105 length += buffers.get(i).remaining();
106 return length;
107 }
108
109 public int getSize()
110 {
111 return buffers.size();
112 }
113
114 public void recycle()
115 {
116 for (int i = 0; i < buffers.size(); ++i)
117 {
118 ByteBuffer buffer = buffers.get(i);
119 if (recycles.get(i))
120 byteBufferPool.release(buffer);
121 }
122 buffers.clear();
123 recycles.clear();
124 }
125 }
126
127
128 class Bucket
129 {
130 private final ByteBufferPool _pool;
131 private final int _capacity;
132 private final AtomicInteger _space;
133 private final Queue<ByteBuffer> _queue= new ConcurrentArrayQueue<>();
134
135 public Bucket(ByteBufferPool pool, int bufferSize,int maxSize)
136 {
137 _pool=pool;
138 _capacity=bufferSize;
139 _space=maxSize>0?new AtomicInteger(maxSize):null;
140 }
141
142 public void release(ByteBuffer buffer)
143 {
144 BufferUtil.clear(buffer);
145 if (_space==null)
146 _queue.offer(buffer);
147 else if (_space.decrementAndGet()>=0)
148 _queue.offer(buffer);
149 else
150 _space.incrementAndGet();
151 }
152
153 public ByteBuffer acquire(boolean direct)
154 {
155 ByteBuffer buffer = _queue.poll();
156 if (buffer == null)
157 return _pool.newByteBuffer(_capacity,direct);
158 if (_space!=null)
159 _space.incrementAndGet();
160 return buffer;
161 }
162
163 public void clear()
164 {
165 if (_space==null)
166 _queue.clear();
167 else
168 {
169 int s=_space.getAndSet(0);
170 while(s-->0)
171 {
172 if (_queue.poll()==null)
173 _space.incrementAndGet();
174 }
175 }
176 }
177
178 boolean isEmpty()
179 {
180 return _queue.isEmpty();
181 }
182
183 int size()
184 {
185 return _queue.size();
186 }
187
188 @Override
189 public String toString()
190 {
191 return String.format("Bucket@%x{%d,%d}",hashCode(),_capacity,_queue.size());
192 }
193 }
194
195
196 }