001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.mina.util.byteaccess; 021 022import java.util.ArrayList; 023import java.util.Stack; 024 025import org.apache.mina.core.buffer.IoBuffer; 026 027/** 028 * Creates <code>ByteArray</code>s, using a pool to reduce allocation where possible. 029 * 030 * WARNING: This code has never been run! 031 * 032 * 033 * @author <a href="http://mina.apache.org">Apache MINA Project</a> 034 */ 035public class ByteArrayPool implements ByteArrayFactory { 036 037 private final int MAX_BITS = 32; 038 039 private boolean freed; 040 041 private final boolean direct; 042 043 private ArrayList<Stack<DirectBufferByteArray>> freeBuffers; 044 045 private int freeBufferCount = 0; 046 047 private long freeMemory = 0; 048 049 private final int maxFreeBuffers; 050 051 private final int maxFreeMemory; 052 053 /** 054 * Creates a new instance of ByteArrayPool. 055 * 056 * @param direct 057 * If we should use direct buffers 058 * @param maxFreeBuffers 059 * The maximum number of free buffers 060 * @param maxFreeMemory 061 * The maximum amount of free memory allowed 062 */ 063 public ByteArrayPool(boolean direct, int maxFreeBuffers, int maxFreeMemory) { 064 this.direct = direct; 065 freeBuffers = new ArrayList<Stack<DirectBufferByteArray>>(); 066 for (int i = 0; i < MAX_BITS; i++) { 067 freeBuffers.add(new Stack<DirectBufferByteArray>()); 068 } 069 this.maxFreeBuffers = maxFreeBuffers; 070 this.maxFreeMemory = maxFreeMemory; 071 this.freed = false; 072 } 073 074 /** 075 * Creates a new instance of a {@link ByteArray} 076 * 077 * @param size 078 * The size of the array to build 079 */ 080 public ByteArray create(int size) { 081 if (size < 1) { 082 throw new IllegalArgumentException("Buffer size must be at least 1: " + size); 083 } 084 int bits = bits(size); 085 synchronized (this) { 086 if (!freeBuffers.get(bits).isEmpty()) { 087 DirectBufferByteArray ba = freeBuffers.get(bits).pop(); 088 ba.setFreed(false); 089 ba.getSingleIoBuffer().limit(size); 090 return ba; 091 } 092 } 093 IoBuffer bb; 094 int bbSize = 1 << bits; 095 bb = IoBuffer.allocate(bbSize, direct); 096 bb.limit(size); 097 DirectBufferByteArray ba = new DirectBufferByteArray(bb); 098 ba.setFreed(false); 099 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}