| Index: base/android/java/src/org/chromium/base/BaseObserverList.java
|
| diff --git a/base/android/java/src/org/chromium/base/ObserverList.java b/base/android/java/src/org/chromium/base/BaseObserverList.java
|
| similarity index 74%
|
| copy from base/android/java/src/org/chromium/base/ObserverList.java
|
| copy to base/android/java/src/org/chromium/base/BaseObserverList.java
|
| index e812b0de4341e0ac21fed05c71b1a268abb18c0d..6410422fc1c6ca97fae3564aba5dde5720b4d64b 100644
|
| --- a/base/android/java/src/org/chromium/base/ObserverList.java
|
| +++ b/base/android/java/src/org/chromium/base/BaseObserverList.java
|
| @@ -1,4 +1,4 @@
|
| -// Copyright 2013 The Chromium Authors. All rights reserved.
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| @@ -12,7 +12,7 @@ import java.util.NoSuchElementException;
|
| import javax.annotation.concurrent.NotThreadSafe;
|
|
|
| /**
|
| - * A container for a list of observers.
|
| + * A container for a list of (optionally wrapped) observers.
|
| * <p/>
|
| * This container can be modified during iteration without invalidating the iterator.
|
| * So, it safely handles the case of an observer removing itself or other observers from the list
|
| @@ -27,27 +27,31 @@ import javax.annotation.concurrent.NotThreadSafe;
|
| * thread this is created.
|
| *
|
| * @param <E> The type of observers that this list should hold.
|
| + * @param <Wrapper> The wrapper type for each added observer, useful when the storage of an
|
| + * observer instance should be different than the observer type itself,
|
| + * e.g., for storing WeakReferences to the underlying observer). For most
|
| + * cases this will be identical to the observer type E.
|
| */
|
| @NotThreadSafe
|
| -public class ObserverList<E> implements Iterable<E> {
|
| - /**
|
| - * Extended iterator interface that provides rewind functionality.
|
| - */
|
| - public interface RewindableIterator<E> extends Iterator<E> {
|
| - /**
|
| - * Rewind the iterator back to the beginning.
|
| - *
|
| - * If we need to iterate multiple times, we can avoid iterator object reallocation by using
|
| - * this method.
|
| - */
|
| - public void rewind();
|
| - }
|
| +abstract class BaseObserverList<E, Wrapper> implements Iterable<E> {
|
|
|
| - public final List<E> mObservers = new ArrayList<E>();
|
| + public final List<Wrapper> mObservers = new ArrayList<Wrapper>();
|
| private int mIterationDepth = 0;
|
| private int mCount = 0;
|
|
|
| - public ObserverList() {}
|
| + /**
|
| + * Override to provide translation from the externally visible Observer
|
| + * type to the underlying storage type.
|
| + */
|
| + abstract Wrapper wrap(E obs);
|
| +
|
| + /**
|
| + * Override to provide translation from the underlying storage type to the
|
| + * externally visible observer type.
|
| + */
|
| + abstract E unwrap(Wrapper wrapper);
|
| +
|
| + public BaseObserverList() {}
|
|
|
| /**
|
| * Add an observer to the list.
|
| @@ -59,13 +63,13 @@ public class ObserverList<E> implements Iterable<E> {
|
| */
|
| public boolean addObserver(E obs) {
|
| // Avoid adding null elements to the list as they may be removed on a compaction.
|
| - if (obs == null || mObservers.contains(obs)) {
|
| + if (obs == null || hasObserver(obs)) {
|
| return false;
|
| }
|
|
|
| // Structurally modifying the underlying list here. This means we
|
| // cannot use the underlying list's iterator to iterate over the list.
|
| - boolean result = mObservers.add(obs);
|
| + boolean result = mObservers.add(wrap(obs));
|
| assert result;
|
|
|
| ++mCount;
|
| @@ -82,7 +86,7 @@ public class ObserverList<E> implements Iterable<E> {
|
| return false;
|
| }
|
|
|
| - int index = mObservers.indexOf(obs);
|
| + int index = indexOf(obs);
|
| if (index == -1) {
|
| return false;
|
| }
|
| @@ -100,7 +104,7 @@ public class ObserverList<E> implements Iterable<E> {
|
| }
|
|
|
| public boolean hasObserver(E obs) {
|
| - return mObservers.contains(obs);
|
| + return indexOf(obs) != -1;
|
| }
|
|
|
| public void clear() {
|
| @@ -154,12 +158,21 @@ public class ObserverList<E> implements Iterable<E> {
|
| private void compact() {
|
| assert mIterationDepth == 0;
|
| for (int i = mObservers.size() - 1; i >= 0; i--) {
|
| - if (mObservers.get(i) == null) {
|
| + if (getObserverAt(i) == null) {
|
| mObservers.remove(i);
|
| }
|
| }
|
| }
|
|
|
| + private int indexOf(E obs) {
|
| + for (int i = 0; i < mObservers.size(); ++i) {
|
| + if (getObserverAt(i) == obs) {
|
| + return i;
|
| + }
|
| + }
|
| + return -1;
|
| + }
|
| +
|
| private void incrementIterationDepth() {
|
| mIterationDepth++;
|
| }
|
| @@ -179,7 +192,7 @@ public class ObserverList<E> implements Iterable<E> {
|
| }
|
|
|
| private E getObserverAt(int index) {
|
| - return mObservers.get(index);
|
| + return unwrap(mObservers.get(index));
|
| }
|
|
|
| private class ObserverListIterator implements RewindableIterator<E> {
|
| @@ -188,15 +201,15 @@ public class ObserverList<E> implements Iterable<E> {
|
| private boolean mIsExhausted = false;
|
|
|
| private ObserverListIterator() {
|
| - ObserverList.this.incrementIterationDepth();
|
| - mListEndMarker = ObserverList.this.capacity();
|
| + BaseObserverList.this.incrementIterationDepth();
|
| + mListEndMarker = BaseObserverList.this.capacity();
|
| }
|
|
|
| @Override
|
| public void rewind() {
|
| compactListIfNeeded();
|
| - ObserverList.this.incrementIterationDepth();
|
| - mListEndMarker = ObserverList.this.capacity();
|
| + BaseObserverList.this.incrementIterationDepth();
|
| + mListEndMarker = BaseObserverList.this.capacity();
|
| mIsExhausted = false;
|
| mIndex = 0;
|
| }
|
| @@ -205,7 +218,7 @@ public class ObserverList<E> implements Iterable<E> {
|
| public boolean hasNext() {
|
| int lookupIndex = mIndex;
|
| while (lookupIndex < mListEndMarker
|
| - && ObserverList.this.getObserverAt(lookupIndex) == null) {
|
| + && BaseObserverList.this.getObserverAt(lookupIndex) == null) {
|
| lookupIndex++;
|
| }
|
| if (lookupIndex < mListEndMarker) return true;
|
| @@ -218,10 +231,10 @@ public class ObserverList<E> implements Iterable<E> {
|
| @Override
|
| public E next() {
|
| // Advance if the current element is null.
|
| - while (mIndex < mListEndMarker && ObserverList.this.getObserverAt(mIndex) == null) {
|
| + while (mIndex < mListEndMarker && BaseObserverList.this.getObserverAt(mIndex) == null) {
|
| mIndex++;
|
| }
|
| - if (mIndex < mListEndMarker) return ObserverList.this.getObserverAt(mIndex++);
|
| + if (mIndex < mListEndMarker) return BaseObserverList.this.getObserverAt(mIndex++);
|
|
|
| // We have reached the end of the list, allow for compaction.
|
| compactListIfNeeded();
|
| @@ -236,7 +249,7 @@ public class ObserverList<E> implements Iterable<E> {
|
| private void compactListIfNeeded() {
|
| if (!mIsExhausted) {
|
| mIsExhausted = true;
|
| - ObserverList.this.decrementIterationDepthAndCompactIfNeeded();
|
| + BaseObserverList.this.decrementIterationDepthAndCompactIfNeeded();
|
| }
|
| }
|
| }
|
|
|