18f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown/*
28f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * Copyright (C) 2013 The Android Open Source Project
38f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown *
48f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
58f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * you may not use this file except in compliance with the License.
68f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * You may obtain a copy of the License at
78f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown *
88f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
98f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown *
108f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * Unless required by applicable law or agreed to in writing, software
118f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
128f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * See the License for the specific language governing permissions and
148f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * limitations under the License.
158f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown */
168f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
178f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownpackage com.android.accessorydisplay.common;
188f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
198f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport java.nio.ByteBuffer;
208f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
218f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown/**
228f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * Maintains a bounded pool of buffers.  Attempts to acquire buffers beyond the maximum
238f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * count will block until other buffers are released.
248f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown */
258f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownfinal class BufferPool {
268f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    private final int mInitialBufferSize;
278f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    private final int mMaxBufferSize;
288f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    private final ByteBuffer[] mBuffers;
298f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    private int mAllocated;
308f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    private int mAvailable;
318f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
328f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    public BufferPool(int initialBufferSize, int maxBufferSize, int maxBuffers) {
338f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        mInitialBufferSize = initialBufferSize;
348f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        mMaxBufferSize = maxBufferSize;
358f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        mBuffers = new ByteBuffer[maxBuffers];
368f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    }
378f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
388f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    public ByteBuffer acquire(int needed) {
398f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        synchronized (this) {
408f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            for (;;) {
418f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                if (mAvailable != 0) {
428f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                    mAvailable -= 1;
438f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                    return grow(mBuffers[mAvailable], needed);
448f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                }
458f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
468f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                if (mAllocated < mBuffers.length) {
478f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                    mAllocated += 1;
488f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                    return ByteBuffer.allocate(chooseCapacity(mInitialBufferSize, needed));
498f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                }
508f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
518f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                try {
528f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                    wait();
538f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                } catch (InterruptedException ex) {
548f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                }
558f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            }
568f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        }
578f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    }
588f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
598f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    public void release(ByteBuffer buffer) {
608f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        synchronized (this) {
618f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            buffer.clear();
628f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            mBuffers[mAvailable++] = buffer;
638f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            notifyAll();
648f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        }
658f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    }
668f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
678f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    public ByteBuffer grow(ByteBuffer buffer, int needed) {
688f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        int capacity = buffer.capacity();
698f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        if (capacity < needed) {
708f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            final ByteBuffer oldBuffer = buffer;
718f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            capacity = chooseCapacity(capacity, needed);
728f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            buffer = ByteBuffer.allocate(capacity);
738f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            oldBuffer.flip();
748f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            buffer.put(oldBuffer);
758f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        }
768f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        return buffer;
778f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    }
788f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
798f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    private int chooseCapacity(int capacity, int needed) {
808f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        while (capacity < needed) {
818f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            capacity *= 2;
828f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        }
838f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        if (capacity > mMaxBufferSize) {
848f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            if (needed > mMaxBufferSize) {
858f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                throw new IllegalArgumentException("Requested size " + needed
868f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                        + " is larger than maximum buffer size " + mMaxBufferSize + ".");
878f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            }
888f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            capacity = mMaxBufferSize;
898f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        }
908f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        return capacity;
918f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    }
928f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown}
93