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