1/*
2 * Copyright (C) 2012 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.gallery3d.data;
18
19import com.android.gallery3d.util.ThreadPool.JobContext;
20
21import java.io.FileDescriptor;
22import java.io.FileInputStream;
23import java.io.IOException;
24import java.util.ArrayList;
25
26public class BytesBufferPool {
27
28    private static final int READ_STEP = 4096;
29
30    public static class BytesBuffer {
31        public byte[] data;
32        public int offset;
33        public int length;
34
35        private BytesBuffer(int capacity) {
36            this.data = new byte[capacity];
37        }
38
39        // an helper function to read content from FileDescriptor
40        public void readFrom(JobContext jc, FileDescriptor fd) throws IOException {
41            FileInputStream fis = new FileInputStream(fd);
42            length = 0;
43            try {
44                int capacity = data.length;
45                while (true) {
46                    int step = Math.min(READ_STEP, capacity - length);
47                    int rc = fis.read(data, length, step);
48                    if (rc < 0 || jc.isCancelled()) return;
49                    length += rc;
50
51                    if (length == capacity) {
52                        byte[] newData = new byte[data.length * 2];
53                        System.arraycopy(data, 0, newData, 0, data.length);
54                        data = newData;
55                        capacity = data.length;
56                    }
57                }
58            } finally {
59                fis.close();
60            }
61        }
62    }
63
64    private final int mPoolSize;
65    private final int mBufferSize;
66    private final ArrayList<BytesBuffer> mList;
67
68    public BytesBufferPool(int poolSize, int bufferSize) {
69        mList = new ArrayList<BytesBuffer>(poolSize);
70        mPoolSize = poolSize;
71        mBufferSize = bufferSize;
72    }
73
74    public synchronized BytesBuffer get() {
75        int n = mList.size();
76        return n > 0 ? mList.remove(n - 1) : new BytesBuffer(mBufferSize);
77    }
78
79    public synchronized void recycle(BytesBuffer buffer) {
80        if (buffer.data.length != mBufferSize) return;
81        if (mList.size() < mPoolSize) {
82            buffer.offset = 0;
83            buffer.length = 0;
84            mList.add(buffer);
85        }
86    }
87
88    public synchronized void clear() {
89        mList.clear();
90    }
91}
92