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   */
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       * Creates a new instance of ByteArrayPool.
52       *
53       * @param direct
54       *  If we should use direct buffers
55       * @param maxFreeBuffers
56       *  The maximum number of free buffers
57       * @param maxFreeMemory
58       *  The maximum amount of free memory allowed
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       * Creates a new instance of a {@link ByteArray}
75       * 
76       * @param size
77       *  The size of the array to build
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      * Frees the buffers
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 }