1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.util.byteaccess;
21
22 import java.util.ArrayList;
23 import java.util.Stack;
24
25 import org.apache.mina.core.buffer.IoBuffer;
26
27
28
29
30
31
32
33
34
35 public class ByteArrayPool implements ByteArrayFactory {
36
37 private final int MAX_BITS = 32;
38
39 private boolean freed;
40
41 private final boolean direct;
42
43 private ArrayList<Stack<DirectBufferByteArray>> freeBuffers;
44
45 private int freeBufferCount = 0;
46
47 private long freeMemory = 0;
48
49 private final int maxFreeBuffers;
50
51 private final int maxFreeMemory;
52
53
54
55
56
57
58
59
60
61
62
63 public ByteArrayPool(boolean direct, int maxFreeBuffers, int maxFreeMemory) {
64 this.direct = direct;
65 freeBuffers = new ArrayList<Stack<DirectBufferByteArray>>();
66 for (int i = 0; i < MAX_BITS; i++) {
67 freeBuffers.add(new Stack<DirectBufferByteArray>());
68 }
69 this.maxFreeBuffers = maxFreeBuffers;
70 this.maxFreeMemory = maxFreeMemory;
71 this.freed = false;
72 }
73
74
75
76
77
78
79
80 public ByteArray create(int size) {
81 if (size < 1) {
82 throw new IllegalArgumentException("Buffer size must be at least 1: " + size);
83 }
84 int bits = bits(size);
85 synchronized (this) {
86 if (!freeBuffers.get(bits).isEmpty()) {
87 DirectBufferByteArray ba = freeBuffers.get(bits).pop();
88 ba.setFreed(false);
89 ba.getSingleIoBuffer().limit(size);
90 return ba;
91 }
92 }
93 IoBuffer bb;
94 int bbSize = 1 << bits;
95 bb = IoBuffer.allocate(bbSize, direct);
96 bb.limit(size);
97 DirectBufferByteArray ba = new DirectBufferByteArray(bb);
98 ba.setFreed(false);
99 return ba;
100 }
101
102 private int bits(int index) {
103 int bits = 0;
104 while (1 << bits < index) {
105 bits++;
106 }
107 return bits;
108 }
109
110
111
112
113
114 public void free() {
115 synchronized (this) {
116 if (freed) {
117 throw new IllegalStateException("Already freed.");
118 }
119 freed = true;
120 freeBuffers.clear();
121 freeBuffers = null;
122 }
123 }
124
125 private class DirectBufferByteArray extends BufferByteArray {
126
127 private boolean freed;
128
129 public DirectBufferByteArray(IoBuffer bb) {
130 super(bb);
131 }
132
133 public void setFreed(boolean freed) {
134 this.freed = freed;
135 }
136
137 @Override
138 public void free() {
139 synchronized (this) {
140 if (freed) {
141 throw new IllegalStateException("Already freed.");
142 }
143 freed = true;
144 }
145 int bits = bits(last());
146 synchronized (ByteArrayPool.this) {
147 if (freeBuffers != null && freeBufferCount < maxFreeBuffers && freeMemory + last() <= maxFreeMemory) {
148 freeBuffers.get(bits).push(this);
149 freeBufferCount++;
150 freeMemory += last();
151 return;
152 }
153 }
154 }
155
156 }
157
158 }