1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.accessorydisplay.common; 18 19import java.nio.ByteBuffer; 20 21/** 22 * Maintains a bounded pool of buffers. Attempts to acquire buffers beyond the maximum 23 * count will block until other buffers are released. 24 */ 25final class BufferPool { 26 private final int mInitialBufferSize; 27 private final int mMaxBufferSize; 28 private final ByteBuffer[] mBuffers; 29 private int mAllocated; 30 private int mAvailable; 31 32 public BufferPool(int initialBufferSize, int maxBufferSize, int maxBuffers) { 33 mInitialBufferSize = initialBufferSize; 34 mMaxBufferSize = maxBufferSize; 35 mBuffers = new ByteBuffer[maxBuffers]; 36 } 37 38 public ByteBuffer acquire(int needed) { 39 synchronized (this) { 40 for (;;) { 41 if (mAvailable != 0) { 42 mAvailable -= 1; 43 return grow(mBuffers[mAvailable], needed); 44 } 45 46 if (mAllocated < mBuffers.length) { 47 mAllocated += 1; 48 return ByteBuffer.allocate(chooseCapacity(mInitialBufferSize, needed)); 49 } 50 51 try { 52 wait(); 53 } catch (InterruptedException ex) { 54 } 55 } 56 } 57 } 58 59 public void release(ByteBuffer buffer) { 60 synchronized (this) { 61 buffer.clear(); 62 mBuffers[mAvailable++] = buffer; 63 notifyAll(); 64 } 65 } 66 67 public ByteBuffer grow(ByteBuffer buffer, int needed) { 68 int capacity = buffer.capacity(); 69 if (capacity < needed) { 70 final ByteBuffer oldBuffer = buffer; 71 capacity = chooseCapacity(capacity, needed); 72 buffer = ByteBuffer.allocate(capacity); 73 oldBuffer.flip(); 74 buffer.put(oldBuffer); 75 } 76 return buffer; 77 } 78 79 private int chooseCapacity(int capacity, int needed) { 80 while (capacity < needed) { 81 capacity *= 2; 82 } 83 if (capacity > mMaxBufferSize) { 84 if (needed > mMaxBufferSize) { 85 throw new IllegalArgumentException("Requested size " + needed 86 + " is larger than maximum buffer size " + mMaxBufferSize + "."); 87 } 88 capacity = mMaxBufferSize; 89 } 90 return capacity; 91 } 92} 93