1f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu/*
2f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu * Copyright (C) 2009 The Android Open Source Project
3f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu *
4f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu * Licensed under the Apache License, Version 2.0 (the "License");
5f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu * you may not use this file except in compliance with the License.
6f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu * You may obtain a copy of the License at
7f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu *
8f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu *      http://www.apache.org/licenses/LICENSE-2.0
9f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu *
10f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu * Unless required by applicable law or agreed to in writing, software
11f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu * distributed under the License is distributed on an "AS IS" BASIS,
12f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu * See the License for the specific language governing permissions and
14f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu * limitations under the License.
15f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu */
16f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu
17f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescupackage android.util;
18f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu
19f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu/**
20f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu * Helper class for crating pools of objects. An example use looks like this:
21f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu * <pre>
22f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu * public class MyPooledClass {
23f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu *
24f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu *     private static final SynchronizedPool<MyPooledClass> sPool =
25f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu *             new SynchronizedPool<MyPooledClass>(10);
26f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu *
27f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu *     public static MyPooledClass obtain() {
28f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu *         MyPooledClass instance = sPool.acquire();
29f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu *         return (instance != null) ? instance : new MyPooledClass();
30f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu *     }
31f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu *
32f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu *     public void recycle() {
33f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu *          // Clear state if needed.
34f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu *          sPool.release(this);
35f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu *     }
36f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu *
37f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu *     . . .
38f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu * }
39f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu * </pre>
40f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu *
41f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu * @hide
42f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu */
43f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescupublic final class Pools {
44f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu
45f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu    /**
46f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu     * Interface for managing a pool of objects.
47f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu     *
48f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu     * @param <T> The pooled type.
49f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu     */
50f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu    public static interface Pool<T> {
51f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu
52f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        /**
53f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu         * @return An instance from the pool if such, null otherwise.
54f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu         */
55f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        public T acquire();
56f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu
57f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        /**
58f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu         * Release an instance to the pool.
59f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu         *
60f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu         * @param instance The instance to release.
61f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu         * @return Whether the instance was put in the pool.
62f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu         *
63f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu         * @throws IllegalStateException If the instance is already in the pool.
64f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu         */
65f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        public boolean release(T instance);
66f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu    }
67f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu
68f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu    private Pools() {
69f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        /* do nothing - hiding constructor */
70f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu    }
71f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu
72f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu    /**
73f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu     * Simple (non-synchronized) pool of objects.
74f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu     *
75f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu     * @param <T> The pooled type.
76f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu     */
77f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu    public static class SimplePool<T> implements Pool<T> {
78f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        private final Object[] mPool;
79f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu
80f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        private int mPoolSize;
81f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu
82f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        /**
83f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu         * Creates a new instance.
84f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu         *
85f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu         * @param maxPoolSize The max pool size.
86f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu         *
87f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu         * @throws IllegalArgumentException If the max pool size is less than zero.
88f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu         */
89f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        public SimplePool(int maxPoolSize) {
90f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu            if (maxPoolSize <= 0) {
91f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu                throw new IllegalArgumentException("The max pool size must be > 0");
92f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu            }
93f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu            mPool = new Object[maxPoolSize];
94f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        }
95f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu
96f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        @Override
97f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        @SuppressWarnings("unchecked")
98f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        public T acquire() {
99f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu            if (mPoolSize > 0) {
100f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu                final int lastPooledIndex = mPoolSize - 1;
101f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu                T instance = (T) mPool[lastPooledIndex];
102f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu                mPool[lastPooledIndex] = null;
103f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu                mPoolSize--;
104f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu                return instance;
105f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu            }
106f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu            return null;
107f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        }
108f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu
109f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        @Override
110f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        public boolean release(T instance) {
111f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu            if (isInPool(instance)) {
112f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu                throw new IllegalStateException("Already in the pool!");
113f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu            }
114f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu            if (mPoolSize < mPool.length) {
115f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu                mPool[mPoolSize] = instance;
116f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu                mPoolSize++;
117f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu                return true;
118f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu            }
119f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu            return false;
120f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        }
121f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu
122f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        private boolean isInPool(T instance) {
123f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu            for (int i = 0; i < mPoolSize; i++) {
124f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu                if (mPool[i] == instance) {
125f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu                    return true;
126f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu                }
127f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu            }
128f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu            return false;
129f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        }
130f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu    }
131f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu
132f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu    /**
133f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu     * Synchronized) pool of objects.
134f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu     *
135f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu     * @param <T> The pooled type.
136f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu     */
137f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu    public static class SynchronizedPool<T> extends SimplePool<T> {
138f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        private final Object mLock = new Object();
139f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu
140f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        /**
141f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu         * Creates a new instance.
142f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu         *
143f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu         * @param maxPoolSize The max pool size.
144f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu         *
145f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu         * @throws IllegalArgumentException If the max pool size is less than zero.
146f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu         */
147f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        public SynchronizedPool(int maxPoolSize) {
148f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu            super(maxPoolSize);
149f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        }
150f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu
151f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        @Override
152f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        public T acquire() {
153f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu            synchronized (mLock) {
154f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu                return super.acquire();
155f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu            }
156f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        }
157f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu
158f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        @Override
159f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        public boolean release(T element) {
160f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu            synchronized (mLock) {
161f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu                return super.release(element);
162f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu            }
163f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu        }
164f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu    }
165f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu}