| Index: base/android/java/src/org/chromium/base/ObserverList.java
|
| diff --git a/base/android/java/src/org/chromium/base/ObserverList.java b/base/android/java/src/org/chromium/base/ObserverList.java
|
| index e812b0de4341e0ac21fed05c71b1a268abb18c0d..5c893217751845a4257fec795f5d50d2ad3d90b1 100644
|
| --- a/base/android/java/src/org/chromium/base/ObserverList.java
|
| +++ b/base/android/java/src/org/chromium/base/ObserverList.java
|
| @@ -4,240 +4,23 @@
|
|
|
| package org.chromium.base;
|
|
|
| -import java.util.ArrayList;
|
| -import java.util.Iterator;
|
| -import java.util.List;
|
| -import java.util.NoSuchElementException;
|
| -
|
| -import javax.annotation.concurrent.NotThreadSafe;
|
| -
|
| /**
|
| - * A container for a list of 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
|
| - * while observers are being notified.
|
| - * <p/>
|
| - * The implementation (and the interface) is heavily influenced by the C++ ObserverList.
|
| - * Notable differences:
|
| - * - The iterator implements NOTIFY_EXISTING_ONLY.
|
| - * - The FOR_EACH_OBSERVER closure is left to the clients to implement in terms of iterator().
|
| - * <p/>
|
| - * This class is not threadsafe. Observers MUST be added, removed and will be notified on the same
|
| - * thread this is created.
|
| + * A container for a list of observers. See BaseObserverList for details.
|
| *
|
| * @param <E> The type of observers that this list should hold.
|
| */
|
| -@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();
|
| - }
|
| -
|
| - public final List<E> mObservers = new ArrayList<E>();
|
| - private int mIterationDepth = 0;
|
| - private int mCount = 0;
|
| +public class ObserverList<E> extends BaseObserverList<E, E> {
|
|
|
| public ObserverList() {}
|
|
|
| - /**
|
| - * Add an observer to the list.
|
| - * <p/>
|
| - * An observer should not be added to the same list more than once. If an iteration is already
|
| - * in progress, this observer will be not be visible during that iteration.
|
| - *
|
| - * @return true if the observer list changed as a result of the call.
|
| - */
|
| - 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)) {
|
| - 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);
|
| - assert result;
|
| -
|
| - ++mCount;
|
| - return true;
|
| - }
|
| -
|
| - /**
|
| - * Remove an observer from the list if it is in the list.
|
| - *
|
| - * @return true if an element was removed as a result of this call.
|
| - */
|
| - public boolean removeObserver(E obs) {
|
| - if (obs == null) {
|
| - return false;
|
| - }
|
| -
|
| - int index = mObservers.indexOf(obs);
|
| - if (index == -1) {
|
| - return false;
|
| - }
|
| -
|
| - if (mIterationDepth == 0) {
|
| - // No one is iterating over the list.
|
| - mObservers.remove(index);
|
| - } else {
|
| - mObservers.set(index, null);
|
| - }
|
| - --mCount;
|
| - assert mCount >= 0;
|
| -
|
| - return true;
|
| - }
|
| -
|
| - public boolean hasObserver(E obs) {
|
| - return mObservers.contains(obs);
|
| - }
|
| -
|
| - public void clear() {
|
| - mCount = 0;
|
| -
|
| - if (mIterationDepth == 0) {
|
| - mObservers.clear();
|
| - return;
|
| - }
|
| -
|
| - int size = mObservers.size();
|
| - for (int i = 0; i < size; i++) {
|
| - mObservers.set(i, null);
|
| - }
|
| - }
|
| -
|
| @Override
|
| - public Iterator<E> iterator() {
|
| - return new ObserverListIterator();
|
| - }
|
| -
|
| - /**
|
| - * It's the same as {@link ObserverList#iterator()} but the return type is
|
| - * {@link RewindableIterator}. Use this iterator type if you need to use
|
| - * {@link RewindableIterator#rewind()}.
|
| - */
|
| - public RewindableIterator<E> rewindableIterator() {
|
| - return new ObserverListIterator();
|
| - }
|
| -
|
| - /**
|
| - * Returns the number of observers currently registered in the ObserverList.
|
| - * This is equivalent to the number of non-empty spaces in |mObservers|.
|
| - */
|
| - public int size() {
|
| - return mCount;
|
| + final E wrap(E obs) {
|
| + return obs;
|
| }
|
|
|
| - /**
|
| - * Returns true if the ObserverList contains no observers.
|
| - */
|
| - public boolean isEmpty() {
|
| - return mCount == 0;
|
| - }
|
| -
|
| - /**
|
| - * Compact the underlying list be removing null elements.
|
| - * <p/>
|
| - * Should only be called when mIterationDepth is zero.
|
| - */
|
| - private void compact() {
|
| - assert mIterationDepth == 0;
|
| - for (int i = mObservers.size() - 1; i >= 0; i--) {
|
| - if (mObservers.get(i) == null) {
|
| - mObservers.remove(i);
|
| - }
|
| - }
|
| - }
|
| -
|
| - private void incrementIterationDepth() {
|
| - mIterationDepth++;
|
| - }
|
| -
|
| - private void decrementIterationDepthAndCompactIfNeeded() {
|
| - mIterationDepth--;
|
| - assert mIterationDepth >= 0;
|
| - if (mIterationDepth == 0) compact();
|
| - }
|
| -
|
| - /**
|
| - * Returns the size of the underlying storage of the ObserverList.
|
| - * It will take into account the empty spaces inside |mObservers|.
|
| - */
|
| - private int capacity() {
|
| - return mObservers.size();
|
| - }
|
| -
|
| - private E getObserverAt(int index) {
|
| - return mObservers.get(index);
|
| - }
|
| -
|
| - private class ObserverListIterator implements RewindableIterator<E> {
|
| - private int mListEndMarker;
|
| - private int mIndex = 0;
|
| - private boolean mIsExhausted = false;
|
| -
|
| - private ObserverListIterator() {
|
| - ObserverList.this.incrementIterationDepth();
|
| - mListEndMarker = ObserverList.this.capacity();
|
| - }
|
| -
|
| - @Override
|
| - public void rewind() {
|
| - compactListIfNeeded();
|
| - ObserverList.this.incrementIterationDepth();
|
| - mListEndMarker = ObserverList.this.capacity();
|
| - mIsExhausted = false;
|
| - mIndex = 0;
|
| - }
|
| -
|
| - @Override
|
| - public boolean hasNext() {
|
| - int lookupIndex = mIndex;
|
| - while (lookupIndex < mListEndMarker
|
| - && ObserverList.this.getObserverAt(lookupIndex) == null) {
|
| - lookupIndex++;
|
| - }
|
| - if (lookupIndex < mListEndMarker) return true;
|
| -
|
| - // We have reached the end of the list, allow for compaction.
|
| - compactListIfNeeded();
|
| - return false;
|
| - }
|
| -
|
| - @Override
|
| - public E next() {
|
| - // Advance if the current element is null.
|
| - while (mIndex < mListEndMarker && ObserverList.this.getObserverAt(mIndex) == null) {
|
| - mIndex++;
|
| - }
|
| - if (mIndex < mListEndMarker) return ObserverList.this.getObserverAt(mIndex++);
|
| -
|
| - // We have reached the end of the list, allow for compaction.
|
| - compactListIfNeeded();
|
| - throw new NoSuchElementException();
|
| - }
|
| -
|
| - @Override
|
| - public void remove() {
|
| - throw new UnsupportedOperationException();
|
| - }
|
| -
|
| - private void compactListIfNeeded() {
|
| - if (!mIsExhausted) {
|
| - mIsExhausted = true;
|
| - ObserverList.this.decrementIterationDepthAndCompactIfNeeded();
|
| - }
|
| - }
|
| + @Override
|
| + final E unwrap(E wrapper) {
|
| + return wrapper;
|
| }
|
| }
|
| +
|
|
|