1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
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 }