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