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.concurrent.ConcurrentHashMap;
23 import java.util.concurrent.ConcurrentMap;
24 import java.util.concurrent.atomic.AtomicInteger;
25
26 import org.eclipse.jetty.util.BufferUtil;
27
28 public class MappedByteBufferPool implements ByteBufferPool
29 {
30 private final ConcurrentMap<Integer, Bucket> directBuffers = new ConcurrentHashMap<>();
31 private final ConcurrentMap<Integer, Bucket> heapBuffers = new ConcurrentHashMap<>();
32 private final int _factor;
33 private final int _maxQueue;
34
35 public MappedByteBufferPool()
36 {
37 this(-1);
38 }
39
40 public MappedByteBufferPool(int factor)
41 {
42 this(factor,-1);
43 }
44
45 public MappedByteBufferPool(int factor,int maxQueue)
46 {
47 _factor = factor<=0?1024:factor;
48 _maxQueue=maxQueue;
49 }
50
51 @Override
52 public ByteBuffer acquire(int size, boolean direct)
53 {
54 int b = bucketFor(size);
55 ConcurrentMap<Integer, Bucket> buffers = bucketsFor(direct);
56
57 Bucket bucket = buffers.get(b);
58 if (bucket==null)
59 return newByteBuffer(b*_factor, direct);
60 return bucket.acquire(direct);
61 }
62
63 protected ByteBuffer newByteBuffer(int capacity, boolean direct)
64 {
65 return direct ? BufferUtil.allocateDirect(capacity)
66 : BufferUtil.allocate(capacity);
67 }
68
69 @Override
70 public void release(ByteBuffer buffer)
71 {
72 if (buffer == null)
73 return;
74
75
76 assert((buffer.capacity() % _factor) == 0);
77
78 int b = bucketFor(buffer.capacity());
79 ConcurrentMap<Integer, Bucket> buckets = bucketsFor(buffer.isDirect());
80
81 Bucket bucket = buckets.computeIfAbsent(b,bi->new Bucket(b*_factor,_maxQueue));
82 bucket.release(buffer);
83 }
84
85 public void clear()
86 {
87 directBuffers.clear();
88 heapBuffers.clear();
89 }
90
91 private int bucketFor(int size)
92 {
93 int bucket = size / _factor;
94 if (size % _factor > 0)
95 ++bucket;
96 return bucket;
97 }
98
99
100 ConcurrentMap<Integer, Bucket> bucketsFor(boolean direct)
101 {
102 return direct ? directBuffers : heapBuffers;
103 }
104
105 public static class Tagged extends MappedByteBufferPool
106 {
107 private final AtomicInteger tag = new AtomicInteger();
108
109 @Override
110 protected ByteBuffer newByteBuffer(int capacity, boolean direct)
111 {
112 ByteBuffer buffer = super.newByteBuffer(capacity + 4, direct);
113 buffer.limit(buffer.capacity());
114 buffer.putInt(tag.incrementAndGet());
115 ByteBuffer slice = buffer.slice();
116 BufferUtil.clear(slice);
117 return slice;
118 }
119 }
120 }