View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
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   * Creates <code>ByteArray</code>s, using a pool to reduce allocation where possible.
31   *
32   * WARNING: This code has never been run!
33   * 
34   *
35   * @author The Apache MINA Project (dev@mina.apache.org)
36   * @version $Rev$, $Date$
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       * Creates a new instance of ByteArrayPool.
53       *
54       * @param direct
55       *  If we should use direct buffers
56       * @param maxFreeBuffers
57       *  The maximum number of free buffers
58       * @param maxFreeMemory
59       *  The maximum amount of free memory allowed
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       * Creates a new instance of a {@link ByteArray}
76       * 
77       * @param size
78       *  The size of the array to build
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      * Frees the buffers
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 }