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
17
18package android.support.v4.util;
19
20
21/**
22 * Helper class for creating pools of objects. An example use looks like this:
23 * <pre>
24 * public class MyPooledClass {
25 *
26 *     private static final SynchronizedPool<MyPooledClass> sPool =
27 *             new SynchronizedPool<MyPooledClass>(10);
28 *
29 *     public static MyPooledClass obtain() {
30 *         MyPooledClass instance = sPool.acquire();
31 *         return (instance != null) ? instance : new MyPooledClass();
32 *     }
33 *
34 *     public void recycle() {
35 *          // Clear state if needed.
36 *          sPool.release(this);
37 *     }
38 *
39 *     . . .
40 * }
41 * </pre>
42 *
43 */
44public final class Pools {
45
46    /**
47     * Interface for managing a pool of objects.
48     *
49     * @param <T> The pooled type.
50     */
51    public static interface Pool<T> {
52
53        /**
54         * @return An instance from the pool if such, null otherwise.
55         */
56        public T acquire();
57
58        /**
59         * Release an instance to the pool.
60         *
61         * @param instance The instance to release.
62         * @return Whether the instance was put in the pool.
63         *
64         * @throws IllegalStateException If the instance is already in the pool.
65         */
66        public boolean release(T instance);
67    }
68
69    private Pools() {
70        /* do nothing - hiding constructor */
71    }
72
73    /**
74     * Simple (non-synchronized) pool of objects.
75     *
76     * @param <T> The pooled type.
77     */
78    public static class SimplePool<T> implements Pool<T> {
79        private final Object[] mPool;
80
81        private int mPoolSize;
82
83        /**
84         * Creates a new instance.
85         *
86         * @param maxPoolSize The max pool size.
87         *
88         * @throws IllegalArgumentException If the max pool size is less than zero.
89         */
90        public SimplePool(int maxPoolSize) {
91            if (maxPoolSize <= 0) {
92                throw new IllegalArgumentException("The max pool size must be > 0");
93            }
94            mPool = new Object[maxPoolSize];
95        }
96
97        @Override
98        @SuppressWarnings("unchecked")
99        public T acquire() {
100            if (mPoolSize > 0) {
101                final int lastPooledIndex = mPoolSize - 1;
102                T instance = (T) mPool[lastPooledIndex];
103                mPool[lastPooledIndex] = null;
104                mPoolSize--;
105                return instance;
106            }
107            return null;
108        }
109
110        @Override
111        public boolean release(T instance) {
112            if (isInPool(instance)) {
113                throw new IllegalStateException("Already in the pool!");
114            }
115            if (mPoolSize < mPool.length) {
116                mPool[mPoolSize] = instance;
117                mPoolSize++;
118                return true;
119            }
120            return false;
121        }
122
123        private boolean isInPool(T instance) {
124            for (int i = 0; i < mPoolSize; i++) {
125                if (mPool[i] == instance) {
126                    return true;
127                }
128            }
129            return false;
130        }
131    }
132
133    /**
134     * Synchronized) pool of objects.
135     *
136     * @param <T> The pooled type.
137     */
138    public static class SynchronizedPool<T> extends SimplePool<T> {
139        private final Object mLock = new Object();
140
141        /**
142         * Creates a new instance.
143         *
144         * @param maxPoolSize The max pool size.
145         *
146         * @throws IllegalArgumentException If the max pool size is less than zero.
147         */
148        public SynchronizedPool(int maxPoolSize) {
149            super(maxPoolSize);
150        }
151
152        @Override
153        public T acquire() {
154            synchronized (mLock) {
155                return super.acquire();
156            }
157        }
158
159        @Override
160        public boolean release(T element) {
161            synchronized (mLock) {
162                return super.release(element);
163            }
164        }
165    }
166}
167