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
23 import java.util.ArrayList;
24 import java.util.Stack;
25
26 import org.apache.mina.core.buffer.IoBuffer;
27
28
29
30
31
32
33
34
35
36
37
38 public class ByteArrayPool implements ByteArrayFactory
39 {
40
41 private final int MAX_BITS = 32;
42
43 private boolean freed;
44 private final boolean direct;
45 private ArrayList<Stack<DirectBufferByteArray>> freeBuffers;
46 private int freeBufferCount = 0;
47 private long freeMemory = 0;
48 private final int maxFreeBuffers;
49 private final int maxFreeMemory;
50
51
52
53
54
55
56
57
58
59
60
61 public ByteArrayPool( boolean direct, int maxFreeBuffers, int maxFreeMemory )
62 {
63 this.direct = direct;
64 freeBuffers = new ArrayList<Stack<DirectBufferByteArray>>();
65 for ( int i = 0; i < MAX_BITS; i++ )
66 {
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 {
82 if ( size < 1 )
83 {
84 throw new IllegalArgumentException( "Buffer size must be at least 1: " + size );
85 }
86 int bits = bits( size );
87 synchronized ( this )
88 {
89 if ( !freeBuffers.isEmpty() )
90 {
91 DirectBufferByteArray ba = freeBuffers.get( bits ).pop();
92 ba.setFreed( false );
93 ba.getSingleIoBuffer().limit( size );
94 return ba;
95 }
96 }
97 IoBuffer bb;
98 int bbSize = 1 << bits;
99 bb = IoBuffer.allocate( bbSize, direct );
100 bb.limit( size );
101 DirectBufferByteArray ba = new DirectBufferByteArray( bb );
102 ba.setFreed( false );
103 return ba;
104 }
105
106
107 private int bits( int index )
108 {
109 int bits = 0;
110 while ( 1 << bits < index )
111 {
112 bits++;
113 }
114 return bits;
115 }
116
117
118
119
120
121 public void free()
122 {
123 synchronized ( this )
124 {
125 if ( freed )
126 {
127 throw new IllegalStateException( "Already freed." );
128 }
129 freed = true;
130 freeBuffers.clear();
131 freeBuffers = null;
132 }
133 }
134
135 private class DirectBufferByteArray extends BufferByteArray
136 {
137
138 public boolean freed;
139
140
141 public DirectBufferByteArray( IoBuffer bb )
142 {
143 super( bb );
144 }
145
146
147 public void setFreed( boolean freed )
148 {
149 this.freed = freed;
150 }
151
152
153 @Override
154 public void free()
155 {
156 synchronized ( this )
157 {
158 if ( freed )
159 {
160 throw new IllegalStateException( "Already freed." );
161 }
162 freed = true;
163 }
164 int bits = bits( last() );
165 synchronized ( ByteArrayPool.this )
166 {
167 if ( freeBuffers != null && freeBufferCount < maxFreeBuffers && freeMemory + last() <= maxFreeMemory )
168 {
169 freeBuffers.get( bits ).push( this );
170 freeBufferCount++;
171 freeMemory += last();
172 return;
173 }
174 }
175 }
176
177 }
178
179 }