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  import java.util.ArrayList;
23  import java.util.Stack;
24  
25  import org.apache.mina.core.buffer.IoBuffer;
26  
27  /**
28   * Creates <code>ByteArray</code>s, using a pool to reduce allocation where possible.
29   *
30   * WARNING: This code has never been run!
31   * 
32   *
33   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
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       * Creates a new instance of ByteArrayPool.
55       *
56       * @param direct
57       *  If we should use direct buffers
58       * @param maxFreeBuffers
59       *  The maximum number of free buffers
60       * @param maxFreeMemory
61       *  The maximum amount of free memory allowed
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       * 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          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      * Frees the buffers
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 }