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