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 import android.compat.annotation.UnsupportedAppUsage; 20 21 /** 22 * Helper class for crating 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 * @hide 44 */ 45 @android.ravenwood.annotation.RavenwoodKeepWholeClass 46 public final class Pools { 47 48 /** 49 * Interface for managing a pool of objects. 50 * 51 * @param <T> The pooled type. 52 */ 53 public static interface Pool<T> { 54 55 /** 56 * @return An instance from the pool if such, null otherwise. 57 */ 58 @UnsupportedAppUsage acquire()59 public T acquire(); 60 61 /** 62 * Release an instance to the pool. 63 * 64 * @param instance The instance to release. 65 * @return Whether the instance was put in the pool. 66 * 67 * @throws IllegalStateException If the instance is already in the pool. 68 */ 69 @UnsupportedAppUsage release(T instance)70 public boolean release(T instance); 71 } 72 Pools()73 private Pools() { 74 /* do nothing - hiding constructor */ 75 } 76 77 /** 78 * Simple (non-synchronized) pool of objects. 79 * 80 * @param <T> The pooled type. 81 */ 82 public static class SimplePool<T> implements Pool<T> { 83 @UnsupportedAppUsage 84 private final Object[] mPool; 85 86 private int mPoolSize; 87 88 /** 89 * Creates a new instance. 90 * 91 * @param maxPoolSize The max pool size. 92 * 93 * @throws IllegalArgumentException If the max pool size is less than zero. 94 */ 95 @UnsupportedAppUsage SimplePool(int maxPoolSize)96 public SimplePool(int maxPoolSize) { 97 if (maxPoolSize <= 0) { 98 throw new IllegalArgumentException("The max pool size must be > 0"); 99 } 100 mPool = new Object[maxPoolSize]; 101 } 102 103 @Override 104 @SuppressWarnings("unchecked") 105 @UnsupportedAppUsage acquire()106 public T acquire() { 107 if (mPoolSize > 0) { 108 final int lastPooledIndex = mPoolSize - 1; 109 T instance = (T) mPool[lastPooledIndex]; 110 mPool[lastPooledIndex] = null; 111 mPoolSize--; 112 return instance; 113 } 114 return null; 115 } 116 117 @Override 118 @UnsupportedAppUsage release(T instance)119 public boolean release(T instance) { 120 if (isInPool(instance)) { 121 throw new IllegalStateException("Already in the pool!"); 122 } 123 if (mPoolSize < mPool.length) { 124 mPool[mPoolSize] = instance; 125 mPoolSize++; 126 return true; 127 } 128 return false; 129 } 130 isInPool(T instance)131 private boolean isInPool(T instance) { 132 for (int i = 0; i < mPoolSize; i++) { 133 if (mPool[i] == instance) { 134 return true; 135 } 136 } 137 return false; 138 } 139 } 140 141 /** 142 * Synchronized pool of objects. 143 * 144 * @param <T> The pooled type. 145 */ 146 public static class SynchronizedPool<T> extends SimplePool<T> { 147 private final Object mLock; 148 149 /** 150 * Creates a new instance. 151 * 152 * @param maxPoolSize The max pool size. 153 * @param lock an optional custom object to synchronize on 154 * 155 * @throws IllegalArgumentException If the max pool size is less than zero. 156 */ SynchronizedPool(int maxPoolSize, Object lock)157 public SynchronizedPool(int maxPoolSize, Object lock) { 158 super(maxPoolSize); 159 mLock = lock; 160 } 161 162 /** @see #SynchronizedPool(int, Object) */ 163 @UnsupportedAppUsage SynchronizedPool(int maxPoolSize)164 public SynchronizedPool(int maxPoolSize) { 165 this(maxPoolSize, new Object()); 166 } 167 168 @Override 169 @UnsupportedAppUsage acquire()170 public T acquire() { 171 synchronized (mLock) { 172 return super.acquire(); 173 } 174 } 175 176 @Override 177 @UnsupportedAppUsage release(T element)178 public boolean release(T element) { 179 synchronized (mLock) { 180 return super.release(element); 181 } 182 } 183 } 184 } 185