AI 143894: am: CL 143890 Fixes #1749387. Improve the pooling of the VelocityTracker class. This introduces a new, hidden, API for pooling objects easily.
Original author: romainguy Merged from: //branches/donutburger/... Automated import of CL 143894
This commit is contained in:
committed by
The Android Open Source Project
parent
2c62f84add
commit
d1b3dd058d
86
core/java/android/util/FinitePool.java
Normal file
86
core/java/android/util/FinitePool.java
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.util;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
class FinitePool<T extends Poolable<T>> implements Pool<T> {
|
||||
/**
|
||||
* Factory used to create new pool objects
|
||||
*/
|
||||
private final PoolableManager<T> mManager;
|
||||
/**
|
||||
* Maximum number of objects in the pool
|
||||
*/
|
||||
private final int mLimit;
|
||||
/**
|
||||
* If true, mLimit is ignored
|
||||
*/
|
||||
private final boolean mInfinite;
|
||||
|
||||
/**
|
||||
* Next object to acquire
|
||||
*/
|
||||
private T mRoot;
|
||||
/**
|
||||
* Number of objects in the pool
|
||||
*/
|
||||
private int mPoolCount;
|
||||
|
||||
FinitePool(PoolableManager<T> manager) {
|
||||
mManager = manager;
|
||||
mLimit = 0;
|
||||
mInfinite = true;
|
||||
}
|
||||
|
||||
FinitePool(PoolableManager<T> manager, int limit) {
|
||||
if (limit <= 0) throw new IllegalArgumentException("The pool limit must be > 0");
|
||||
|
||||
mManager = manager;
|
||||
mLimit = limit;
|
||||
mInfinite = false;
|
||||
}
|
||||
|
||||
public T acquire() {
|
||||
T element;
|
||||
|
||||
if (mRoot != null) {
|
||||
element = mRoot;
|
||||
mRoot = element.getNextPoolable();
|
||||
mPoolCount--;
|
||||
} else {
|
||||
element = mManager.newInstance();
|
||||
}
|
||||
|
||||
if (element != null) {
|
||||
element.setNextPoolable(null);
|
||||
mManager.onAcquired(element);
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
public void release(T element) {
|
||||
if (mInfinite || mPoolCount < mLimit) {
|
||||
mPoolCount++;
|
||||
element.setNextPoolable(mRoot);
|
||||
mRoot = element;
|
||||
}
|
||||
mManager.onReleased(element);
|
||||
}
|
||||
}
|
||||
25
core/java/android/util/Pool.java
Normal file
25
core/java/android/util/Pool.java
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.util;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public interface Pool<T extends Poolable<T>> {
|
||||
public abstract T acquire();
|
||||
public abstract void release(T element);
|
||||
}
|
||||
41
core/java/android/util/PoolFactory.java
Normal file
41
core/java/android/util/PoolFactory.java
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.util;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public class PoolFactory {
|
||||
private PoolFactory() {
|
||||
}
|
||||
|
||||
public static <T extends Poolable<T>> Pool<T> simplePool(PoolableManager<T> manager) {
|
||||
return new FinitePool<T>(manager);
|
||||
}
|
||||
|
||||
public static <T extends Poolable<T>> Pool<T> finitePool(PoolableManager<T> manager, int limit) {
|
||||
return new FinitePool<T>(manager, limit);
|
||||
}
|
||||
|
||||
public static <T extends Poolable<T>> Pool<T> synchronizedPool(Pool<T> pool) {
|
||||
return new SynchronizedPool<T>(pool);
|
||||
}
|
||||
|
||||
public static <T extends Poolable<T>> Pool<T> synchronizedPool(Pool<T> pool, Object lock) {
|
||||
return new SynchronizedPool<T>(pool, lock);
|
||||
}
|
||||
}
|
||||
25
core/java/android/util/Poolable.java
Normal file
25
core/java/android/util/Poolable.java
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.util;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public interface Poolable<T> {
|
||||
void setNextPoolable(T element);
|
||||
T getNextPoolable();
|
||||
}
|
||||
27
core/java/android/util/PoolableManager.java
Normal file
27
core/java/android/util/PoolableManager.java
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.util;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public interface PoolableManager<T extends Poolable<T>> {
|
||||
T newInstance();
|
||||
|
||||
void onAcquired(T element);
|
||||
void onReleased(T element);
|
||||
}
|
||||
48
core/java/android/util/SynchronizedPool.java
Normal file
48
core/java/android/util/SynchronizedPool.java
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.util;
|
||||
|
||||
/**
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
class SynchronizedPool<T extends Poolable<T>> implements Pool<T> {
|
||||
private final Pool<T> mPool;
|
||||
private final Object mLock;
|
||||
|
||||
public SynchronizedPool(Pool<T> pool) {
|
||||
mPool = pool;
|
||||
mLock = this;
|
||||
}
|
||||
|
||||
public SynchronizedPool(Pool<T> pool, Object lock) {
|
||||
mPool = pool;
|
||||
mLock = lock;
|
||||
}
|
||||
|
||||
public T acquire() {
|
||||
synchronized (mLock) {
|
||||
return mPool.acquire();
|
||||
}
|
||||
}
|
||||
|
||||
public void release(T element) {
|
||||
synchronized (mLock) {
|
||||
mPool.release(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,10 @@ package android.view;
|
||||
|
||||
import android.util.Config;
|
||||
import android.util.Log;
|
||||
import android.util.Poolable;
|
||||
import android.util.Pool;
|
||||
import android.util.PoolFactory;
|
||||
import android.util.PoolableManager;
|
||||
|
||||
/**
|
||||
* Helper for tracking the velocity of touch events, for implementing
|
||||
@@ -28,53 +32,72 @@ import android.util.Log;
|
||||
* {@link #computeCurrentVelocity(int)} and then {@link #getXVelocity()}
|
||||
* and {@link #getXVelocity()}.
|
||||
*/
|
||||
public final class VelocityTracker {
|
||||
public final class VelocityTracker implements Poolable<VelocityTracker> {
|
||||
static final String TAG = "VelocityTracker";
|
||||
static final boolean DEBUG = false;
|
||||
static final boolean localLOGV = DEBUG || Config.LOGV;
|
||||
|
||||
|
||||
static final int NUM_PAST = 10;
|
||||
static final int LONGEST_PAST_TIME = 200;
|
||||
|
||||
|
||||
static final VelocityTracker[] mPool = new VelocityTracker[1];
|
||||
|
||||
private static final Pool<VelocityTracker> sPool = PoolFactory.synchronizedPool(
|
||||
PoolFactory.finitePool(new PoolableManager<VelocityTracker>() {
|
||||
public VelocityTracker newInstance() {
|
||||
return new VelocityTracker();
|
||||
}
|
||||
|
||||
public void onAcquired(VelocityTracker element) {
|
||||
element.clear();
|
||||
}
|
||||
|
||||
public void onReleased(VelocityTracker element) {
|
||||
}
|
||||
}, 2));
|
||||
|
||||
final float mPastX[] = new float[NUM_PAST];
|
||||
final float mPastY[] = new float[NUM_PAST];
|
||||
final long mPastTime[] = new long[NUM_PAST];
|
||||
|
||||
|
||||
float mYVelocity;
|
||||
float mXVelocity;
|
||||
|
||||
|
||||
private VelocityTracker mNext;
|
||||
|
||||
/**
|
||||
* Retrieve a new VelocityTracker object to watch the velocity of a
|
||||
* motion. Be sure to call {@link #recycle} when done. You should
|
||||
* generally only maintain an active object while tracking a movement,
|
||||
* so that the VelocityTracker can be re-used elsewhere.
|
||||
*
|
||||
*
|
||||
* @return Returns a new VelocityTracker.
|
||||
*/
|
||||
static public VelocityTracker obtain() {
|
||||
synchronized (mPool) {
|
||||
VelocityTracker vt = mPool[0];
|
||||
if (vt != null) {
|
||||
vt.clear();
|
||||
mPool[0] = null;
|
||||
return vt;
|
||||
}
|
||||
return new VelocityTracker();
|
||||
}
|
||||
return sPool.acquire();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a VelocityTracker object back to be re-used by others. You must
|
||||
* not touch the object after calling this function.
|
||||
*/
|
||||
public void recycle() {
|
||||
synchronized (mPool) {
|
||||
mPool[0] = this;
|
||||
}
|
||||
sPool.release(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public void setNextPoolable(VelocityTracker element) {
|
||||
mNext = element;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public VelocityTracker getNextPoolable() {
|
||||
return mNext;
|
||||
}
|
||||
|
||||
private VelocityTracker() {
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,10 @@ import android.util.AttributeSet;
|
||||
import android.util.EventLog;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.util.Poolable;
|
||||
import android.util.Pool;
|
||||
import android.util.PoolFactory;
|
||||
import android.util.PoolableManager;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
@@ -7827,26 +7831,24 @@ public class View implements Drawable.Callback, KeyEvent.Callback {
|
||||
* For performance purposes, this class also implements a pool of up to
|
||||
* POOL_LIMIT objects that get reused. This reduces memory allocations
|
||||
* whenever possible.
|
||||
*
|
||||
* The pool is implemented as a linked list of InvalidateInfo object with
|
||||
* the root pointing to the next available InvalidateInfo. If the root
|
||||
* is null (i.e. when all instances from the pool have been acquired),
|
||||
* then a new InvalidateInfo is created and returned to the caller.
|
||||
*
|
||||
* An InvalidateInfo is sent back to the pool by calling its release()
|
||||
* method. If the pool is full the object is simply discarded.
|
||||
*
|
||||
* This implementation follows the object pool pattern used in the
|
||||
* MotionEvent class.
|
||||
*/
|
||||
static class InvalidateInfo {
|
||||
static class InvalidateInfo implements Poolable<InvalidateInfo> {
|
||||
private static final int POOL_LIMIT = 10;
|
||||
private static final Object sLock = new Object();
|
||||
private static final Pool<InvalidateInfo> sPool = PoolFactory.synchronizedPool(
|
||||
PoolFactory.finitePool(new PoolableManager<InvalidateInfo>() {
|
||||
public InvalidateInfo newInstance() {
|
||||
return new InvalidateInfo();
|
||||
}
|
||||
|
||||
private static int sAcquiredCount = 0;
|
||||
private static InvalidateInfo sRoot;
|
||||
public void onAcquired(InvalidateInfo element) {
|
||||
}
|
||||
|
||||
private InvalidateInfo next;
|
||||
public void onReleased(InvalidateInfo element) {
|
||||
}
|
||||
}, POOL_LIMIT)
|
||||
);
|
||||
|
||||
private InvalidateInfo mNext;
|
||||
|
||||
View target;
|
||||
|
||||
@@ -7855,28 +7857,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback {
|
||||
int right;
|
||||
int bottom;
|
||||
|
||||
public void setNextPoolable(InvalidateInfo element) {
|
||||
mNext = element;
|
||||
}
|
||||
|
||||
public InvalidateInfo getNextPoolable() {
|
||||
return mNext;
|
||||
}
|
||||
|
||||
static InvalidateInfo acquire() {
|
||||
synchronized (sLock) {
|
||||
if (sRoot == null) {
|
||||
return new InvalidateInfo();
|
||||
}
|
||||
|
||||
InvalidateInfo info = sRoot;
|
||||
sRoot = info.next;
|
||||
sAcquiredCount--;
|
||||
|
||||
return info;
|
||||
}
|
||||
return sPool.acquire();
|
||||
}
|
||||
|
||||
void release() {
|
||||
synchronized (sLock) {
|
||||
if (sAcquiredCount < POOL_LIMIT) {
|
||||
sAcquiredCount++;
|
||||
next = sRoot;
|
||||
sRoot = this;
|
||||
}
|
||||
}
|
||||
sPool.release(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user