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 
17 package 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  */
43 public 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          */
acquire()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          */
release(T instance)65         public boolean release(T instance);
66     }
67 
Pools()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          */
SimplePool(int maxPoolSize)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")
acquire()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
release(T instance)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 
isInPool(T instance)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          */
SynchronizedPool(int maxPoolSize)147         public SynchronizedPool(int maxPoolSize) {
148             super(maxPoolSize);
149         }
150 
151         @Override
acquire()152         public T acquire() {
153             synchronized (mLock) {
154                 return super.acquire();
155             }
156         }
157 
158         @Override
release(T element)159         public boolean release(T element) {
160             synchronized (mLock) {
161                 return super.release(element);
162             }
163         }
164     }
165 }