1009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell/* 2009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * Copyright (C) 2013 The Android Open Source Project 3009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * 4009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * Licensed under the Apache License, Version 2.0 (the "License"); 5009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * you may not use this file except in compliance with the License. 6009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * You may obtain a copy of the License at 7009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * 8009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * http://www.apache.org/licenses/LICENSE-2.0 9009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * 10009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * Unless required by applicable law or agreed to in writing, software 11009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * distributed under the License is distributed on an "AS IS" BASIS, 12009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * See the License for the specific language governing permissions and 14009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * limitations under the License. 15009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell */ 16009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell 17009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell 18ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.core.util; 19009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell 20009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell 21ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.NonNull; 22ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.Nullable; 239f498146df152fc38a4004cb7aefdd2d71943205Jake Wharton 24009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell/** 256db4c676e03b3637cc0182ba5475d47e8be62c92Aurimas Liutikas * Helper class for creating pools of objects. An example use looks like this: 26009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * <pre> 27009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * public class MyPooledClass { 28009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * 29009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * private static final SynchronizedPool<MyPooledClass> sPool = 30009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * new SynchronizedPool<MyPooledClass>(10); 31009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * 32009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * public static MyPooledClass obtain() { 33009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * MyPooledClass instance = sPool.acquire(); 34009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * return (instance != null) ? instance : new MyPooledClass(); 35009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * } 36009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * 37009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * public void recycle() { 38009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * // Clear state if needed. 39009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * sPool.release(this); 40009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * } 41009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * 42009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * . . . 43009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * } 44009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * </pre> 45009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * 46009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell */ 47009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powellpublic final class Pools { 48009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell 49009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell /** 50009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * Interface for managing a pool of objects. 51009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * 52009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * @param <T> The pooled type. 53009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell */ 545211222f71426ccfc1f2cca9f5f6bb89c61c9ed5Jake Wharton public interface Pool<T> { 55009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell 56009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell /** 57009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * @return An instance from the pool if such, null otherwise. 58009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell */ 599f498146df152fc38a4004cb7aefdd2d71943205Jake Wharton @Nullable 605211222f71426ccfc1f2cca9f5f6bb89c61c9ed5Jake Wharton T acquire(); 61009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell 62009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell /** 63009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * Release an instance to the pool. 64009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * 65009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * @param instance The instance to release. 66009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * @return Whether the instance was put in the pool. 67009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * 68009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * @throws IllegalStateException If the instance is already in the pool. 69009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell */ 705211222f71426ccfc1f2cca9f5f6bb89c61c9ed5Jake Wharton boolean release(@NonNull T instance); 71009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell } 72009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell 73009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell private Pools() { 74009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell /* do nothing - hiding constructor */ 75009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell } 76009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell 77009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell /** 78009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * Simple (non-synchronized) pool of objects. 79009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * 80009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * @param <T> The pooled type. 81009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell */ 82009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell public static class SimplePool<T> implements Pool<T> { 83009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell private final Object[] mPool; 84009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell 85009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell private int mPoolSize; 86009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell 87009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell /** 88009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * Creates a new instance. 89009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * 90009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * @param maxPoolSize The max pool size. 91009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * 92009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * @throws IllegalArgumentException If the max pool size is less than zero. 93009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell */ 94009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell public SimplePool(int maxPoolSize) { 95009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell if (maxPoolSize <= 0) { 96009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell throw new IllegalArgumentException("The max pool size must be > 0"); 97009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell } 98009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell mPool = new Object[maxPoolSize]; 99009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell } 100009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell 101009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell @Override 102009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell @SuppressWarnings("unchecked") 103009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell public T acquire() { 104009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell if (mPoolSize > 0) { 105009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell final int lastPooledIndex = mPoolSize - 1; 106009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell T instance = (T) mPool[lastPooledIndex]; 107009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell mPool[lastPooledIndex] = null; 108009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell mPoolSize--; 109009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell return instance; 110009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell } 111009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell return null; 112009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell } 113009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell 114009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell @Override 1159f498146df152fc38a4004cb7aefdd2d71943205Jake Wharton public boolean release(@NonNull T instance) { 116009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell if (isInPool(instance)) { 117009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell throw new IllegalStateException("Already in the pool!"); 118009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell } 119009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell if (mPoolSize < mPool.length) { 120009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell mPool[mPoolSize] = instance; 121009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell mPoolSize++; 122009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell return true; 123009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell } 124009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell return false; 125009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell } 126009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell 1279f498146df152fc38a4004cb7aefdd2d71943205Jake Wharton private boolean isInPool(@NonNull T instance) { 128009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell for (int i = 0; i < mPoolSize; i++) { 129009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell if (mPool[i] == instance) { 130009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell return true; 131009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell } 132009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell } 133009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell return false; 134009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell } 135009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell } 136009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell 137009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell /** 138009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * Synchronized) pool of objects. 139009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * 140009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * @param <T> The pooled type. 141009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell */ 142009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell public static class SynchronizedPool<T> extends SimplePool<T> { 143009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell private final Object mLock = new Object(); 144009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell 145009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell /** 146009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * Creates a new instance. 147009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * 148009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * @param maxPoolSize The max pool size. 149009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * 150009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell * @throws IllegalArgumentException If the max pool size is less than zero. 151009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell */ 152009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell public SynchronizedPool(int maxPoolSize) { 153009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell super(maxPoolSize); 154009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell } 155009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell 156009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell @Override 157009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell public T acquire() { 158009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell synchronized (mLock) { 159009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell return super.acquire(); 160009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell } 161009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell } 162009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell 163009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell @Override 1649f498146df152fc38a4004cb7aefdd2d71943205Jake Wharton public boolean release(@NonNull T element) { 165009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell synchronized (mLock) { 166009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell return super.release(element); 167009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell } 168009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell } 169009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell } 170009b4ef9d97e1cc237477e3284fc305bb1438cc9Adam Powell} 171